Có một số mẫu thiết kế bạn có thể sử dụng trong node.js để chạy các hoạt động không đồng bộ tuần tự. Trong tất cả chúng, bạn không thể chạy một vòng lặp chặt chẽ chờ đợi điều gì đó xảy ra - bạn phải để một chuỗi Javascript duy nhất trong node.js chạy và cung cấp cho nó càng nhiều chu kỳ càng tốt.
Lặp lại thủ công
Đặt mã cho một lần lặp trong một hàm cục bộ (tôi thường gọi nó là next()
) và sau đó khi một lần lặp gọi hàm hoàn thành cuối cùng của nó, bạn có thể gọi next()
một lần nữa để bắt đầu lặp lại tiếp theo. Bạn có thể hoàn thành thao tác bằng cách kiểm tra một số điều kiện và không gọi next()
nếu mọi việc đã xong hoặc những dòng đầu tiên của next()
có thể kiểm tra xem bạn đã hoàn thành chưa.
Xem ví dụ mã bên dưới để biết mã của bạn trông như thế nào khi lặp lại thủ công.
Lời hứa theo trình tự
Nếu bạn sử dụng các lời hứa cho các hoạt động không đồng bộ của mình, thì bạn có thể để các lời hứa có chuỗi thực hiện tất cả việc sắp xếp theo trình tự cho bạn như trong p().then(f1).then(f2).then(f3)
. Bạn có thể xem ví dụ về điều đó trong câu trả lời này: Những lời hứa như async.each
.
Sử dụng Mô-đun không đồng bộ
Mô-đun không đồng bộ hỗ trợ một số chức năng quản lý không đồng bộ. Nhiều người thấy nó rất hữu ích - những người khác thích sử dụng lời hứa để giải quyết các vấn đề tương tự. Trong mọi trường hợp, nó có một số chức năng khác nhau để giải trình tự. Ví dụ:nếu bạn muốn lặp lại một mảng không đồng bộ, bạn sẽ sử dụng một cái gì đó như sau:
async.eachSeries(hugeArray, function iterator(item, callback) {
if (inCache(item)) {
callback(null, cache[item]); // if many items are cached, you'll overflow
} else {
doSomeIO(item, callback);
}
}, function done() {
//...
});
Đây là phiên bản mã của bạn thực hiện lặp lại thủ công bằng cách sử dụng next()
tùy chỉnh chức năng lặp.
function runQuery(callback) {
mysql.getConnection(function(err, connection) {
if (err) {
connection.release();
callback(err);
return;
}
var array = [];
var count = 10;
var index = 0;
function next() {
if (index++ < count) {
array.push([index, 'master']);
console.log('100-elements');
connection.beginTransaction(function(err) {
if (err) {
// can't throw here in an async function
// use callback to communicate error
callback(err);
return;
}
var query = "insert into users(username, password) values ?";
connection.query(query, [array], function(err, rows) {
if (!err) {
//commit start
connection.commit(function() {
if (err) {
console.error(err);
connection.rollback(function() {
console.error('rollback error');
callback(err);
return;
});
} else {
console.log("Commit");
// now do the next iteration
next();
} // if err
}); //commit end
} else {
console.log(err);
connection.rollback(function() {
callback(err);
return;
});
} // if
});
});
}
}
});
}