Mã bộ điều khiển cho một số trang Thư viện cục bộ của chúng tôi sẽ phụ thuộc vào kết quả của nhiều yêu cầu không đồng bộ, có thể được yêu cầu chạy theo một số thứ tự cụ thể hoặc song song. Để quản lý kiểm soát luồng và hiển thị các trang khi chúng tôi có sẵn tất cả thông tin bắt buộc, chúng tôi sẽ sử dụng mô-đun không đồng bộ nút phổ biến
Ghi chú. Có một số cách khác để quản lý hành vi không đồng bộ và kiểm soát luồng trong JavaScript, bao gồm các tính năng ngôn ngữ JavaScript tương đối gần đây như Lời hứa
Async có rất nhiều phương pháp hữu ích [xem tài liệu]. Một số chức năng quan trọng hơn là
0 để thực hiện bất kỳ hoạt động nào phải được thực hiện song songasync.parallel[ { one[callback] { /* … */ }, two[callback] { /* … */ }, // … something_else[callback] { /* … */ }, }, // optional callback function [err, results] { // 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value} } ];
1 khi chúng ta cần đảm bảo rằng các hoạt động không đồng bộ được thực hiện theo chuỗiasync.parallel[ { one[callback] { /* … */ }, two[callback] { /* … */ }, // … something_else[callback] { /* … */ }, }, // optional callback function [err, results] { // 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value} } ];
2 cho các hoạt động phải được chạy theo chuỗi, với mỗi hoạt động phụ thuộc vào kết quả của các hoạt động trước đóasync.parallel[ { one[callback] { /* … */ }, two[callback] { /* … */ }, // … something_else[callback] { /* … */ }, }, // optional callback function [err, results] { // 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value} } ];
tại sao nó cần thiết?
Hầu hết các phương thức chúng tôi sử dụng trong Express đều không đồng bộ—bạn chỉ định một thao tác để thực hiện, chuyển một lệnh gọi lại. Phương thức trả về ngay lập tức và cuộc gọi lại được gọi khi thao tác được yêu cầu hoàn tất. Theo quy ước trong Express, các hàm gọi lại chuyển một giá trị lỗi làm tham số đầu tiên [hoặc
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
3 nếu thành công] và kết quả từ hàm [nếu có] làm tham số thứ haiNếu bộ điều khiển chỉ cần thực hiện một thao tác không đồng bộ để lấy thông tin cần thiết để hiển thị trang thì việc triển khai rất dễ dàng—chúng tôi hiển thị mẫu trong hàm gọi lại. Đoạn mã bên dưới hiển thị điều này cho một hàm hiển thị số lượng của mô hình
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
0 [sử dụng phương thức Mongoose async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
1]exports.some_model_count = function [req, res, next] {
SomeModel.countDocuments[
{ a_model_field: "match_value" },
function [err, count] {
// Do something if there is an err.
// …
// On success, render the result by passing count into the render function [here, as the variable 'data'].
res.render["the_template", { data: count }];
}
];
};
Điều gì sẽ xảy ra nếu bạn cần thực hiện nhiều truy vấn không đồng bộ và bạn không thể kết xuất trang cho đến khi tất cả các thao tác hoàn tất? . Vấn đề với cách tiếp cận này là các yêu cầu của chúng tôi sẽ phải được chạy theo chuỗi, mặc dù việc chạy chúng song song có thể hiệu quả hơn. Điều này cũng có thể dẫn đến mã lồng nhau phức tạp, thường được gọi là địa ngục gọi lại
Một giải pháp tốt hơn nhiều là thực hiện song song tất cả các yêu cầu và sau đó có một cuộc gọi lại duy nhất thực thi khi tất cả các truy vấn đã hoàn thành. Đây là loại hoạt động luồng mà mô-đun Async giúp dễ dàng
Hoạt động không đồng bộ song song
Phương pháp
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
0 được sử dụng để chạy song song nhiều hoạt động không đồng bộĐối số đầu tiên của
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
0 là tập hợp các hàm không đồng bộ để chạy [một mảng, đối tượng hoặc có thể lặp lại khác]. Mỗi chức năng được thông qua một async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
4 mà nó phải gọi khi hoàn thành với lỗi async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
5 [có thể là async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
3] và một giá trị async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
7 tùy chọnĐối số thứ hai tùy chọn cho
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
0 là một cuộc gọi lại sẽ được chạy khi tất cả các chức năng trong đối số đầu tiên đã hoàn thành. Cuộc gọi lại được gọi với một đối số lỗi và tập hợp kết quả chứa kết quả của các hoạt động không đồng bộ riêng lẻ. Bộ sưu tập kết quả cùng loại với đối số đầu tiên [i. e. nếu bạn chuyển một mảng các hàm không đồng bộ, lệnh gọi lại cuối cùng sẽ được gọi với một mảng kết quả]. Nếu bất kỳ chức năng song song nào báo cáo lỗi, cuộc gọi lại sẽ được gọi sớm [với giá trị lỗi]Ví dụ dưới đây cho thấy cách nó hoạt động khi chúng ta chuyển một đối tượng làm đối số đầu tiên. Như bạn có thể thấy, các kết quả được trả về trong một đối tượng có cùng tên thuộc tính với các hàm ban đầu được truyền vào
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
Thay vào đó, nếu bạn chuyển một mảng các hàm làm đối số đầu tiên, thì kết quả sẽ là một mảng [kết quả thứ tự mảng sẽ khớp với thứ tự ban đầu mà các hàm được khai báo—chứ không phải thứ tự mà chúng đã hoàn thành]
Hoạt động không đồng bộ trong chuỗi
Phương thức
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
1 được sử dụng để chạy nhiều hoạt động không đồng bộ theo trình tự, khi các chức năng tiếp theo không phụ thuộc vào đầu ra của các chức năng trước đó. Về cơ bản, nó được khai báo và hoạt động giống như async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
0async.series[
{
one[callback] {
// …
},
two[callback] {
// …
},
// …
something_else[callback] {
// …
},
},
// optional callback after the last asynchronous function completes.
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, /* …, */ something_else: some_value}
}
];
Ghi chú. Đặc tả ngôn ngữ ECMAScript [JavaScript] nói rằng thứ tự liệt kê của một đối tượng không được xác định, vì vậy có thể các hàm sẽ không được gọi theo thứ tự như bạn chỉ định chúng trên tất cả các nền tảng. Nếu thứ tự thực sự quan trọng, thì bạn nên truyền một mảng thay vì một đối tượng, như hình bên dưới
________số 8
Hoạt động không đồng bộ phụ thuộc nối tiếp
Phương thức
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
2 được sử dụng để chạy nhiều thao tác không đồng bộ theo trình tự khi mỗi thao tác phụ thuộc vào kết quả của thao tác trước đóCuộc gọi lại được gọi bởi mỗi hàm không đồng bộ chứa
async.parallel[
{
one[callback] {
/* … */
},
two[callback] {
/* … */
},
// …
something_else[callback] {
/* … */
},
},
// optional callback
function [err, results] {
// 'results' is now equal to: {one: 1, two: 2, …, something_else: some_value}
}
];
3 cho đối số đầu tiên và dẫn đến các đối số tiếp theo. Mỗi hàm trong chuỗi lấy các đối số kết quả của hàm gọi lại trước làm tham số đầu tiên và sau đó là hàm gọi lại. Khi tất cả các hoạt động hoàn tất, một cuộc gọi lại cuối cùng được gọi với kết quả của hoạt động cuối cùng. Cách thức hoạt động của điều này sẽ rõ ràng hơn khi bạn xem xét đoạn mã bên dưới [ví dụ này lấy từ tài liệu không đồng bộ]async.waterfall[
[
function [callback] {
callback[null, "one", "two"];
},
function [arg1, arg2, callback] {
// arg1 now equals 'one' and arg2 now equals 'two'
callback[null, "three"];
},
function [arg1, callback] {
// arg1 now equals 'three'
callback[null, "done"];
},
],
function [err, result] {
// result now equals 'done'
}
];
Cài đặt không đồng bộ
Cài đặt mô-đun async bằng trình quản lý gói npm để chúng tôi có thể sử dụng nó trong mã của mình. Bạn làm điều này theo cách thông thường, bằng cách mở một dấu nhắc trong thư mục gốc của dự án LocalLibrary và nhập lệnh sau