Hướng dẫn node js mysql query without callback - nút js truy vấn mysql mà không có lệnh gọi lại

Nói chung, câu trả lời là không, trừ khi bạn sử dụng liên kết với libmysqlclient (hoặc tương tự) phơi bày các giao diện đồng bộ như vậy.

Bạn muốn tránh các giao diện đồng bộ như vậy vì về cơ bản chúng sẽ ngăn bạn làm bất cứ điều gì khác trong khi chức năng đồng bộ đang thực hiện. Ví dụ: nếu bạn có một máy chủ đang chạy, điều đó có nghĩa là bạn không thể phục vụ các máy khách khác. Tất cả họ phải ít nhất phải chờ chức năng đồng bộ của bạn hoàn thành.

Mặc dù vậy, có rất nhiều cách để xử lý các nhiệm vụ không đồng bộ, bao gồm các cuộc gọi lại "thủ công" (rõ ràng), các thư viện trợ giúp dựa trên cuộc gọi lại như

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
5, lời hứa, máy phát điện, async/chờ đợi, v.v. mà không thực sự đồng bộ.

Viết các ứng dụng không đồng bộ trong Node.js có thể khó học, nhưng ngoại trừ một số trường hợp thực sự đơn giản, không thể tránh được. Truy cập cơ sở dữ liệu là một ví dụ về một hoạt động không đồng bộ bởi bản chất. Điều đó có nghĩa là bạn phải chờ kết quả của một truy vấn, nhưng trong khi chờ đợi, chương trình của bạn sẽ tiếp tục thực hiện. Ví dụ, nó có thể thực hiện một số tính toán hoặc gửi một truy vấn khác đến cơ sở dữ liệu song song.

Trong một ngôn ngữ lập trình đồng bộ, truyền thống như PHP, bạn có thể viết đơn giản:

$result = $connection->query( 'SELECT * FROM users WHERE id = 1' );

Trong JavaScript, bạn có ba tùy chọn để viết mã không đồng bộ:

  1. Sử dụng các cuộc gọi lại:
db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );

2. Sử dụng lời hứa:

db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );

3. Sử dụng từ khóa

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
6:

const rows = await db.query( 'SELECT * FROM users WHERE id = 1' );

Lúc đầu, sự khác biệt dường như hoàn toàn là mỹ phẩm. Nó chỉ là cú pháp khác nhau để đạt được điều tương tự. Sự khác biệt trở nên rõ ràng hơn khi bạn cố gắng làm một cái gì đó phức tạp hơn.

Hạn chế của các cuộc gọi lại và lời hứa

Trong bài viết trước đây của tôi, Node.js, MySQL và Promise, tôi đã đưa ra một ví dụ về việc thực hiện một vài truy vấn, từng người một và sau đó đóng kết nối.

Khi sử dụng các cuộc gọi lại đơn giản, điều này yêu cầu làm tổ các chức năng gọi lại và kiểm tra kết quả lỗi trong mỗi chức năng, dẫn đến một cuộc gọi lại địa ngục.

Với lời hứa, mã trở nên thanh lịch hơn, bởi vì bạn có thể chuỗi xử lý nhiều người xử lý

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
7 và sử dụng một trình xử lý
db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
8 cho tất cả các lỗi. Tuy nhiên, trích xuất kết quả truy vấn và đóng kết nối bất kể thành công hay lỗi vẫn đòi hỏi một số nỗ lực.

Tình hình thậm chí còn trở nên tồi tệ hơn khi bạn phải đưa các vòng và điều kiện vào một mã không đồng bộ. Hãy tưởng tượng các mã giả đồng bộ giả thuyết sau đây:

const users = db.query( 'SELECT * FROM users WHERE id = 1' );
for ( const i in users ) {
users[ i ].groups = db.query( '...' );
if ( users[ i ].is_admin )
users[ i ].modules = db.query( '...' );
}

Việc thực hiện mã này không đồng bộ với các cuộc gọi lại sẽ khó và sẽ làm cho mã gần như không thể đọc được. Thật không may, những lời hứa don don làm cho điều này dễ dàng hơn nhiều:

db.query( ‘SELECT * FROM users WHERE id = 1' ).then( users => {
let loop = Promise.resolve();
for ( const i in users ) {
loop = loop.then( () => db.query( '...' )
.then( groups => users[ i ].groups = groups ) );
if ( users[ i ].is_admin ) {
loop = loop.then( () => db.query( '...' )
.then( members => users[ i ].members = members ) );
}
}
return loop.then( () => users );
} );

Mã trên có thể sẽ hoạt động như dự định, nhưng nó không thể đọc được lắm. Khi các hoạt động không đồng bộ được xâu chuỗi động như thế này, thật khó để xác định thứ tự chúng sẽ được thực thi.

Async/Await Way

Ở đây, cùng một mã được triển khai bằng cách sử dụng từ khóa

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
6:

const users = await db.query( 'SELECT * FROM users WHERE id = 1' );
for ( const i in users ) {
users[ i ].groups = await db.query( '...' );
if ( users[ i ].is_admin )
users[ i ].modules = await db.query( '...' );
}

Như bạn có thể thấy, nó gần như giống hệt với ví dụ đồng bộ. Nó sử dụng các cấu trúc lập trình truyền thống, chẳng hạn như vòng lặp và điều kiện, và thứ tự thực hiện trở nên rõ ràng. Đó là lý do tại sao nó rất dễ đọc và viết mã đó.

Xử lý lỗi cũng rõ ràng hơn, bởi vì bạn có thể sử dụng các cấu trúc như thử/bắt và thử/cuối cùng. Điều này giúp dễ dàng hơn để xem trình xử lý lỗi nào được liên kết với một khối mã cụ thể.

Khi bạn mới bắt đầu sử dụng nó, cú pháp Async/Await có vẻ như là một phép thuật đen tối. Điều quan trọng là phải hiểu rằng nó thực sự chỉ là đường cú pháp cho những lời hứa thường xuyên được sử dụng đằng sau hậu trường. Điều này có nghĩa là bạn có thể tự do kết hợp những lời hứa với Async/đang chờ đợi.

Một hàm Async chỉ đơn giản là không có gì khác hơn là một hàm được đảm bảo để trả lại lời hứa. Bạn có thể sử dụng nó như bất kỳ chức năng nào khác trả về lời hứa:

async function foo() {
return 42;
}
foo().then( result => console.log( result ) );

Mã này sẽ in 42.

Mặt khác, trong hàm Async, bạn có thể sử dụng từ khóa

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
6 với bất kỳ lời hứa nào, không chỉ gọi các hàm Async khác:

const foo = Promise.resolve( 42 );console.log( await foo );

Điều này cũng sẽ in 42.

Điều này rất quan trọng, bởi vì chúng ta có thể bọc bất kỳ chức năng hiện tại nào sử dụng các cuộc gọi lại để trả lại lời hứa và gọi chức năng đó bằng cách sử dụng cú pháp Async/Await.

Sử dụng async/chờ đợi với mysql

Hãy để tạo ra một trình bao bọc cơ sở dữ liệu dựa trên lời hứa đơn giản bằng cách sử dụng mô -đun MySQL cho Node.js:

const util = require( 'util' );
const mysql = require( 'mysql' );
function makeDb( config ) {
const connection = mysql.createConnection( config );
return {
query( sql, args ) {
return util.promisify( connection.query )
.call( connection, sql, args );
},
close() {
return util.promisify( connection.end ).call( connection );
}
};
}

Nó tương tự như lớp cơ sở dữ liệu mà tôi đã triển khai trong bài viết trước, chỉ lần này nó là một chức năng nhà máy thay vì một lớp và nó sử dụng chức năng tiện ích Promisify () để giữ cho mọi thứ đơn giản. Nhưng nó hoạt động giống nhau, vì vậy cả chức năng

db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );
1 và
db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );
2 đều trả lại một lời hứa.

Mã ví dụ từ bài viết trước có thể được viết lại bằng Async/Await:

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
0

Chúng tôi có thể thêm hỗ trợ cho các giao dịch bằng cách hứa hẹn các chức năng

db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );
3,
db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );
4 và
db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );
5 trong trình bao bọc cơ sở dữ liệu của chúng tôi:

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
1

Mã trên được viết lại để sử dụng các giao dịch trông như thế này:

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
2

Để tránh lặp lại mã nồi hơi này mỗi lần, chúng ta có thể tạo chức năng trợ giúp thực thi mã không đồng bộ tùy ý trong một giao dịch:

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
3

Như bạn có thể thấy, tham số

db.query( 'SELECT * FROM users WHERE id = 1' ).then( rows => {
// ... use the result ...
} );
6 dự kiến ​​sẽ là một hàm trả lại một lời hứa.

Với chức năng trợ giúp này, mã trên có thể được đơn giản hóa theo điều này:

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
4

Ở đây chúng tôi sử dụng từ khóa

db.query( 'SELECT * FROM users WHERE id = 1', ( err, rows ) => {
// ... use the result ...
} );
5 với chức năng mũi tên để dễ dàng tạo chức năng gọi lại không đồng bộ.

Cập nhật 06/11/2021: Asmike Robinson đã chỉ ra trong nhận xét, một cách tiếp cận khác là sử dụng gói MySQL2, hỗ trợ các hoạt động Async ra khỏi hộp. Nó hoạt động rất giống với các ví dụ trên, nhưng trình bao bọc sử dụng Promisify () không còn cần thiết nữa.: AsMike Robinson pointed out in the comment, an alternative approach is to use the mysql2 package, which supports async operations out of the box. It works very similar to the examples above, but the wrapper using promisify() is no longer necessary.

Ghi chú cuối cùng

Từ kinh nghiệm của tôi, một khi bạn đã quen với việc viết mã bằng cách sử dụng async/chờ đợi, thật khó để tưởng tượng làm thế nào bạn có thể sống mà không có nó. Tuy nhiên, để có thể viết mã không đồng bộ, bạn vẫn cần hiểu những lời hứa và để sử dụng lời hứa, bạn cần hiểu các cuộc gọi lại.

Lưu ý rằng cú pháp Async/Await chỉ hoạt động trong Node.js phiên bản 8 hoặc mới hơn, vì vậy nếu bạn vẫn đang sử dụng phiên bản cũ hơn, bạn nên xem xét cập nhật nó.

Bạn cũng có thể sử dụng Async/đang chờ trong mã phía máy khách nếu bạn đang nhắm mục tiêu các trình duyệt hiện đại. Nếu bạn phải hỗ trợ IE, thì nó cũng có thể với sự trợ giúp của người chuyển đổi và polyfills, nhưng đó là bên ngoài phạm vi của bài viết này.

Làm cách nào để chạy truy vấn nút js trong mysql?

Đây là cách sử dụng MySQL trong nút trong năm bước dễ dàng:..
Tạo một dự án mới: MKDIR MySQL-Test && CD MySQL-TEST ..
Tạo một gói. Tệp JSON: NPM init -Y ..
Cài đặt mô -đun MySQL: NPM Cài đặt MySQL ..
Tạo một ứng dụng. Tệp JS và sao chép trong đoạn trích bên dưới (chỉnh sửa trình giữ chỗ khi thích hợp) ..
Chạy tệp: Ứng dụng nút ..

MySQL truy vấn có đồng bộ không?

Bất kỳ máy khách MySQL nào hỗ trợ giao thức X đều có thể cung cấp thực thi không đồng bộ, bằng cách sử dụng các cuộc gọi lại, lời hứa hoặc bằng cách chờ đợi rõ ràng về một kết quả cụ thể tại thời điểm thực sự cần thiết., either using callbacks, Promises, or by explicitly waiting on a specific result at the moment in time when it is actually needed.

Làm thế nào sử dụng Async đang chờ đợi trong truy vấn MySQL?

Sử dụng async/đang chờ với mysql nhưng nó hoạt động giống nhau, vì vậy cả các hàm truy vấn () và đóng () đều trả về một lời hứa.Như bạn có thể thấy, tham số gọi lại dự kiến sẽ là một hàm trả lại một lời hứa.Ở đây chúng tôi sử dụng từ khóa Async với chức năng mũi tên để dễ dàng tạo chức năng gọi lại không đồng bộ.use the async keyword with an arrow function to easily create an asynchronous callback function.

Node JS có cho phép giao tiếp với MySQL không?

Khi bạn đã chạy và chạy 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 Node.js.Để truy cập cơ sở dữ liệu MySQL với nút.JS, bạn cần một trình điều khiển MySQL. js. To access a MySQL database with Node. js, you need a MySQL driver.