Lời hứa mysql của NodeJS

Một thẻ đã tồn tại với tên chi nhánh được cung cấp. Nhiều lệnh Git chấp nhận cả tên thẻ và tên nhánh, vì vậy việc tạo nhánh này có thể gây ra hành vi không mong muốn. Bạn có chắc chắn muốn tạo nhánh này không?

nút-mysql-lời hứa

Nút. js Trình bao bọc lời hứa của thư viện MySQL

Khởi tạo

cài đặt npm @ikoala/node-mysql-promise

Cách sử dụng

const db = require('@ikoala/node-mysql-promise')
const mysqlConfig = {
  "host": "127.0.0.1",
  "user": "root",
  "password": "abc@123",
  "database": "test"
}
db.create('master', mysqlConfig)

const query = async (val) => {
  const sql = 'SELECT NOW(), ?, 1'
  const params = [val]
  const rs = await db.query(sql, params)
  console.log(rs) // 2020-02-01 15:56:00,foo,1
}

query('foo')

Chức năng trợ giúp

const select = helper.createSelect('table_name', 'primary_key_field');
(async () => {
  await select({ all: true }) // Select all records
  await select(1) // Select primary key id 1
  // Select field `foo` with value `bar`
  await select({ where: {
    foo: 'bar'
  }})
})()

const insert = helper.createInsert('table_name', 'primary_key_field', {
  defaultFields: {
    ctime: () => new Date()
  }
});
(async () => {
  await insert({
    field1: 'foo',
    field2: 'bar'
  }) // foo,bar,[ctime date]
})()

thử nghiệm

# Setup DB Connection and Login Credential
export DB_HOST=127.0.0.1
export DB_USER=root
export DB_PASSWORD=abc@123
export DB_VERBOSE=1 # Optional, enable query log

chạy thử npm

phụ thuộc

mysql - Nút. trình điều khiển js MySQL

chức năng không đồng bộ startServer () { const client = đang chờ MongoClient. kết nối ('mongodb. //máy chủ cục bộ. 27017/quản trị viên', {useNewUrlParser. true}) ứng dụng. định nghĩa bài văn. torrentdb = máy khách. ứng dụng db('torrent'). định nghĩa bài văn. mdb = đang chờ mysql. createPool({ giới hạn kết nối. 5, máy chủ. 'máy chủ cục bộ', người dùng. 'gốc', mật khẩu. '', Hải cảng. 9306, nhiều câu lệnh. đúng }) ứng dụng. lắng nghe (quá trình. env. HẢI CẢNG. 3000, không đồng bộ () => { bảng điều khiển. log(new Date(), 'Máy chủ đang lắng nghe. ') nếu (tiến trình. gửi) { quá trình. gửi('sẵn sàng') } }) }

Giống như hầu hết các hoạt động I/O trong Node. js, truy cập cơ sở dữ liệu không đồng bộ. Đó là một tính năng tuyệt vời, bởi vì các hoạt động khác có thể được thực hiện trong khi chờ đợi kết quả. Nhưng nếu bạn đến từ một ngôn ngữ lập trình khác, điều này có thể thực sự khó chịu

Trong PHP, bạn chỉ cần viết

$results = $connection->query( 'SELECT * FROM some_table' );// the following code is executed after the query is executed

Tất nhiên, phương pháp

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
0 có thể mất một chút thời gian để thực thi, nhưng theo quan điểm của lập trình viên, điều đó không thực sự quan trọng. Nó hoạt động như một hoạt động nguyên tử đơn lẻ, lấy một truy vấn SQL làm đầu vào và trả về một số kết quả làm đầu ra

trong nút. js, bạn phải viết một cái gì đó như thế này

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed

Lưu ý rằng tôi đang sử dụng MySQL (dựa trên thư viện máy khách mysql) làm ví dụ, nhưng điều này cũng đúng với bất kỳ cơ sở dữ liệu nào khác, kể cả những công cụ không có SQL ưa thích đó 🙂

Được rồi, có lẽ ví dụ trên không quá tệ. Nhưng giả sử rằng bạn phải thực hiện lần lượt một số truy vấn. Và sau đó đóng kết nối, đây cũng là một hoạt động không đồng bộ

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}

Bây giờ hãy tưởng tượng rằng có 10 truy vấn lồng nhau như thế này. Và bạn phải thêm xử lý lỗi ở cấp độ của mỗi truy vấn. Và đảm bảo rằng cơ sở dữ liệu được đóng ngay cả khi có lỗi, ở mọi cấp độ

Mã như vậy sẽ rất khó viết theo cách này. Thậm chí còn khó sửa đổi hơn khi bạn phải chèn một truy vấn khác vào đâu đó ở giữa. Và chắc chắn là không thể đọc được

Sử dụng lời hứa

Đó là nơi những lời hứa đến để giải cứu. Nếu bạn chưa quen với khái niệm này, tôi khuyên bạn nên đọc một số phần giới thiệu trước, ví dụ tại đây hoặc tại đây. Mục đích của tôi là cho bạn thấy cách sử dụng thực tế của các lời hứa để thực hiện các truy vấn cơ sở dữ liệu tuần tự, vì vậy tôi cho rằng bạn đã biết chúng là gì

Đầu tiên chúng ta phải “quảng cáo” client cơ sở dữ liệu. Bạn không cần phải làm thủ công, bạn có thể sử dụng một công cụ tự động như công cụ được mô tả ở đây, nhưng việc tạo một lớp bao bọc cho máy khách MySQL thực sự đơn giản

const mysql = require( 'mysql' );class Database {
constructor( config ) {
this.connection = mysql.createConnection( config );
}
query( sql, args ) {
return new Promise( ( resolve, reject ) => {
this.connection.query( sql, args, ( err, rows ) => {
if ( err )
return reject( err );
resolve( rows );
} );
} );
}
close() {
return new Promise( ( resolve, reject ) => {
this.connection.end( err => {
if ( err )
return reject( err );
resolve();
} );
} );
}
}

Hàm tạo chỉ cần tạo một kết nối MySQL mới với cấu hình đã cho. Lưu ý rằng nó chưa mở kết nối. Kết nối được tự động mở khi truy vấn đầu tiên được thực hiện. Đó là lý do tại sao tạo kết nối không phải là hoạt động không đồng bộ

Phương thức

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
0 lấy một chuỗi SQL và một mảng tham số tùy chọn sẽ được chuyển đến truy vấn. Nó trả về một đối tượng
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
2. Lời hứa sẽ được "giải quyết" khi thực hiện xong truy vấn. Các hàng được trả về sẽ là kết quả của lời hứa. Trong trường hợp có lỗi, lời hứa sẽ bị từ chối

Phương pháp

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
3 rất giống nhau. Lời hứa được trả lại được giải quyết khi kết nối bị đóng. Nó không có bất kỳ kết quả

Lưu ý rằng phương thức

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
0 vẫn trả về ngay lập tức, trước khi truy vấn được thực hiện. Để có được kết quả, chúng ta phải gọi phương thức
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
5 của lời hứa được trả về và chỉ định một chức năng sẽ được gọi khi truy vấn kết thúc thực thi

Chúng ta có thể sử dụng lớp

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
6 mới của mình theo cách sau

const select = helper.createSelect('table_name', 'primary_key_field');
(async () => {
  await select({ all: true }) // Select all records
  await select(1) // Select primary key id 1
  // Select field `foo` with value `bar`
  await select({ where: {
    foo: 'bar'
  }})
})()

const insert = helper.createInsert('table_name', 'primary_key_field', {
  defaultFields: {
    ctime: () => new Date()
  }
});
(async () => {
  await insert({
    field1: 'foo',
    field2: 'bar'
  }) // foo,bar,[ctime date]
})()
4

Lúc đầu không có ý nghĩa gì. Mã này gần giống như ví dụ đầu tiên

Tuy nhiên, không giống như các cuộc gọi lại, các lời hứa có thể rất dễ dàng bị xâu chuỗi. Vì vậy, nếu chúng tôi muốn thực hiện một vài truy vấn và sau đó đóng kết nối, chúng tôi có thể làm điều gì đó như thế này

const select = helper.createSelect('table_name', 'primary_key_field');
(async () => {
  await select({ all: true }) // Select all records
  await select(1) // Select primary key id 1
  // Select field `foo` with value `bar`
  await select({ where: {
    foo: 'bar'
  }})
})()

const insert = helper.createInsert('table_name', 'primary_key_field', {
  defaultFields: {
    ctime: () => new Date()
  }
});
(async () => {
  await insert({
    field1: 'foo',
    field2: 'bar'
  }) // foo,bar,[ctime date]
})()
5

Điều này dễ đọc hơn nhiều và có thể dễ dàng mở rộng nếu cần thiết. Tuy nhiên, vẫn còn hai vấn đề với giải pháp này

Trích xuất kết quả

Vấn đề đầu tiên là trong mỗi chức năng gọi lại, chúng tôi chỉ có quyền truy cập vào kết quả của truy vấn cuối cùng. Vì vậy, nếu chúng tôi muốn làm điều gì đó với kết quả của cả hai truy vấn, chúng tôi phải lưu trữ chúng trong các biến cục bộ

const select = helper.createSelect('table_name', 'primary_key_field');
(async () => {
  await select({ all: true }) // Select all records
  await select(1) // Select primary key id 1
  // Select field `foo` with value `bar`
  await select({ where: {
    foo: 'bar'
  }})
})()

const insert = helper.createInsert('table_name', 'primary_key_field', {
  defaultFields: {
    ctime: () => new Date()
  }
});
(async () => {
  await insert({
    field1: 'foo',
    field2: 'bar'
  }) // foo,bar,[ctime date]
})()
6

Lưu ý rằng để chuỗi hoạt động, các chức năng trong

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
5 phải trả lại lời hứa từ phương thức
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
0. Nếu chúng ta bỏ qua từ khóa
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
9, hàm
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
5 tiếp theo sẽ được gọi ngay với
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
1 bằng với
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
2

Xử lý lỗi và đóng kết nối

Ngoài ra, chúng ta không thể quên việc xử lý lỗi. Khi bất kỳ lời hứa nào trong chuỗi bị từ chối và chúng tôi không "bắt" được từ chối, chương trình của chúng tôi sẽ dừng lại với một lỗi nghiêm trọng, giống như trong trường hợp ngoại lệ chưa được xử lý

Chỉ cần thêm một hàm

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
3 vào cuối toàn bộ chuỗi lời hứa là đủ. Khi xảy ra lỗi ở bất kỳ bước nào, tất cả các trình xử lý
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
5 tiếp theo sẽ bị bỏ qua và trình xử lý
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
3 được thực thi. Điều này khá giống với khối
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
6/
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
7

Một vấn đề với giải pháp này là trong trường hợp xảy ra lỗi, kết nối sẽ không bao giờ bị đóng vì việc đóng kết nối cũng sẽ bị bỏ qua. Trong một chương trình đồng bộ, điều này có thể được thực hiện bằng cách thêm mệnh đề

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
8 vào khối
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
6/
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
7

Thật không may, các lời hứa JavaScript chưa có phương thức

const mysql = require( 'mysql' );class Database {
constructor( config ) {
this.connection = mysql.createConnection( config );
}
query( sql, args ) {
return new Promise( ( resolve, reject ) => {
this.connection.query( sql, args, ( err, rows ) => {
if ( err )
return reject( err );
resolve( rows );
} );
} );
}
close() {
return new Promise( ( resolve, reject ) => {
this.connection.end( err => {
if ( err )
return reject( err );
resolve();
} );
} );
}
}
1, mặc dù nó hiện đang ở giai đoạn đề xuất 2, vì vậy rất có thể nó sẽ sớm được thêm vào

Để đảm bảo rằng kết nối luôn được đóng, ngay cả khi có lỗi, chúng ta có thể sử dụng đoạn mã sau

$results = $connection->query( 'SELECT * FROM some_table' );// the following code is executed after the query is executed
2

Hàm thứ hai được truyền cho

connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
// do something with the results here
} );
// the following code is executed *before* the query is executed
5, mà tôi đã đánh dấu bằng phông chữ in đậm, được gọi khi bất kỳ bước nào trước đó trong chuỗi dẫn đến lỗi. Nó đóng kết nối cơ sở dữ liệu và sau đó ném lại lỗi để nó đến trình xử lý
connection.query( 'SELECT * FROM some_table', ( err, rows ) => {
connection.query( 'SELECT * FROM other_table', ( err, rows2 ) => {
connection.close( err => {
// .. do something with all the results
}
}
}
3 cuối cùng

Nếu bạn thường sử dụng mẫu này, sẽ rất hữu ích nếu bạn tách việc tạo và đóng kết nối trong một chức năng riêng biệt như thế này

$results = $connection->query( 'SELECT * FROM some_table' );// the following code is executed after the query is executed
5

Ví dụ có thể được viết lại bằng chức năng này như thế này

$results = $connection->query( 'SELECT * FROM some_table' );// the following code is executed after the query is executed
6

Bạn có thể sử dụng một kỹ thuật tương tự để kết thúc một giao dịch. Giao dịch sẽ được tự động thực hiện khi tất cả các truy vấn được thực hiện thành công hoặc được khôi phục trong trường hợp có lỗi

ghi chú cuối cùng

Lời hứa rất phức tạp và phải mất một thời gian để làm quen với chúng và hiểu đầy đủ về chúng. Nhưng trên thực tế, mã không đồng bộ luôn phức tạp. Các lời hứa làm cho việc viết và suy luận dễ dàng hơn một chút so với các cuộc gọi lại trần. Nếu bạn không tin tôi, hãy thử googling cho "gọi lại địa ngục" 🙂

Một điều làm cho việc viết mã không đồng bộ dễ dàng hơn so với lời hứa là các từ khóa

const mysql = require( 'mysql' );class Database {
constructor( config ) {
this.connection = mysql.createConnection( config );
}
query( sql, args ) {
return new Promise( ( resolve, reject ) => {
this.connection.query( sql, args, ( err, rows ) => {
if ( err )
return reject( err );
resolve( rows );
} );
} );
}
close() {
return new Promise( ( resolve, reject ) => {
this.connection.end( err => {
if ( err )
return reject( err );
resolve();
} );
} );
}
}
4/
const mysql = require( 'mysql' );class Database {
constructor( config ) {
this.connection = mysql.createConnection( config );
}
query( sql, args ) {
return new Promise( ( resolve, reject ) => {
this.connection.query( sql, args, ( err, rows ) => {
if ( err )
return reject( err );
resolve( rows );
} );
} );
}
close() {
return new Promise( ( resolve, reject ) => {
this.connection.end( err => {
if ( err )
return reject( err );
resolve();
} );
} );
}
}
5 mới. Tôi đã sử dụng chúng trong C# một thời gian và tôi thực sự thích chúng. Chúng không được hỗ trợ bởi Node. js 6, nhưng bạn có thể sử dụng Nút. js 8 hoặc Babel

Tôi đã viết phần thứ hai của bài viết này, được gọi là Nút. js, MySQL và async/await, giải thích cách sử dụng cú pháp mới này để thực hiện các thao tác cơ sở dữ liệu không đồng bộ dễ dàng hơn

✉️ Đăng ký Email Blast hàng tuần một lần của CodeBurst, 🐦 Theo dõi CodeBurst trên Twitter, xem 🗺️ Lộ trình dành cho nhà phát triển web năm 2018 và 🕸️ Tìm hiểu về phát triển web Full Stack

Làm cách nào để sử dụng lời hứa trong nút MySQL js?

Để tạo một lời hứa, chúng tôi sử dụng từ khóa hàm tạo “mới” . Đối tượng lời hứa có hai tham số, một cho thành công và một cho thất bại. (giải quyết, bác bỏ). Nó trả về một giá trị với cuộc gọi lại giải quyết và một đối tượng lỗi với từ chối.

NodeJS có thể kết nối với MySQL không?

Khi bạn đã thiết lập và chạy MySQL trên máy tính của mình, bạn có thể truy cập nó bằng cách sử dụng Nút. js . Để truy cập cơ sở dữ liệu MySQL bằng Node. js, bạn cần có trình điều khiển MySQL.

MySQL có tốt cho NodeJS không?

js được kết hợp với MongoDB và các cơ sở dữ liệu NoSQL khác, nhưng Node. js cũng hoạt động tốt với các cơ sở dữ liệu quan hệ như MySQL . Nếu bạn muốn viết một microservice mới với Node. js cho cơ sở dữ liệu hiện có, rất có thể bạn sẽ sử dụng MySQL, một trong những cơ sở dữ liệu mã nguồn mở phổ biến nhất thế giới.

Làm cách nào để nút js lưu trữ dữ liệu trong MySQL?

Bây giờ hãy mở command terminal và chạy lệnh sau. chèn nút. js. .
var mysql = yêu cầu('mysql');
var con = mysql. .
chủ nhà. "máy chủ cục bộ",
người sử dụng. "nguồn gốc",
mật khẩu mở khóa. "12345",