Q: Cách tốt nhất trong Node.js tới 1) có được là kết quả của các cuộc gọi async đầu tiên là gì, 2) lặp qua danh sách, làm cho nhiều cuộc gọi async, và 3) xử lý các kết quả khi mọi thứ đã hoàn tất".
Có nhiều cách tiếp cận. Hand coding, Promises, thư viện Async. "Tốt nhất" là trong mắt của khán giả vì vậy không thực sự cho chúng tôi để nói ở đây. Tôi sử dụng Promises cho tất cả các mã async của tôi. Chúng đã được chuẩn hóa chính xác trong ES6 và có những triển khai tốt, mạnh mẽ (tôi thích Bluebird cho các tính năng bổ sung vượt quá tiêu chuẩn để đơn giản hóa các tác vụ không đồng bộ phức tạp và đó là tính năng promisifyAll()
cung cấp cho bạn giao diện lời hứa trên bất kỳ hoạt động async chuẩn nào sử dụng quy ước gọi lại gọi lại async).
Tôi khuyên bạn nên chống lại các hoạt động không đồng bộ hóa mã hóa tay phức tạp vì việc xử lý lỗi mạnh là rất khó và ngoại lệ có thể bị âm thầm ăn trong các cuộc gọi lại không đồng bộ dẫn đến việc xử lý lỗi bị mất và gỡ lỗi khó khăn. Thư viện Async có lẽ là cách không tốt nhất để làm những việc vì nó cung cấp một số tính năng cơ sở hạ tầng và đồng bộ hóa xung quanh các cuộc gọi lại không đồng bộ.
Cá nhân tôi thích lời hứa. Tôi nghĩ rằng chúng ta sẽ thấy nhiều API không đồng bộ hơn tiêu chuẩn hóa về việc trả lời một lời hứa khi thời gian di chuyển về phía trước vì vậy tôi nghĩ rằng đó là lựa chọn tốt hơn cho một cách tìm kiếm và chương trình hướng tới tương lai.
Hỏi: Lời hứa có phải là lựa chọn tốt ở đây không?
Có, hứa hẹn cho phép bạn chạy một loạt các hoạt động không đồng bộ và sau đó sử dụng một cái gì đó như Promise.all()
để biết khi nào chúng được thực hiện xong. Nó cũng sẽ thu thập tất cả các kết quả từ tất cả các hoạt động không đồng bộ cho bạn.
Q: Được thực hiện()/tiếp theo() một tùy chọn?
Tôi không chắc chắn bạn đang hỏi gì ở đây, nhưng bạn có thể mã thủ công các hoạt động không đồng bộ để chạy song song và biết thời điểm chúng được thực hiện hoặc chạy tuần tự và biết khi nào chúng được thực hiện. Lời hứa làm rất nhiều công việc này cho bạn, nhưng bạn có thể làm điều đó một cách thủ công mà không có chúng.
Hỏi: Có bất kỳ "thành ngữ chuẩn" nào trong Node.js cho loại kịch bản này không?
Nếu sử dụng lời hứa, sẽ có một cách phổ biến để thực hiện việc này. Nếu không sử dụng lời hứa, có thể không phải là "thành ngữ tiêu chuẩn" vì có nhiều cách khác nhau để tự viết mã.
Thực hiện Promise
Dưới đây là một ví dụ sử dụng thư viện Bluebird Promise trong Node.js:
var Promise = require('bluebird');
var connection = Promise.promisifyAll(box.getConnection(req.user.login));
connection.ready(function() {
connection.getFolderItemsAsync(0, null).then(function(result) {
return Promise.map(result.entries, function(item) {
return connection.getFileInfoAsync(item.id);
})
}).then(function(results) {
// array of results here
}, function(err) {
// error here
});
});
Dưới đây là cách hoạt động:
Promisify đối tượng kết nối để tất cả các phương thức của nó đều có một phiên bản trả về một lời hứa (chỉ cần thêm "Async" vào cuối phương thức để gọi cho prom này phiên bản được hợp nhất).
Gọi getFolderItemsAsync()
và lời hứa của mình sẽ giải quyết với result.entries
mảng
Run bản đồ về mảng đó, chạy tất cả các hoạt động song song và trả về một lời hứa mà giải quyết với một loạt các kết quả yêu cầu khi tất cả các hoạt động đã xong.
Kết quả thực tế cho từng mục nhập đạt được với connection.getFileInfoAsync()
.
Tạo trình xử lý xử lý và trình xử lý từ chối. Nếu bất kỳ lỗi nào xảy ra ở bất kỳ nơi nào trong tiến trình, nó sẽ lan truyền tới trình xử lý từ chối. Nếu tất cả các hoạt động thành công, trình xử lý phân giải cuối cùng sẽ được gọi với một mảng kết quả đã sắp xếp.
Phiên bản ở trên sẽ hủy nếu có lỗi và bạn không nhận được kết quả nào ngoài mã lỗi. Nếu bạn muốn tiếp tục với một kết quả null
nếu có một lỗi, sau đó bạn có thể sử dụng một cái gì đó như thế này:
var Promise = require('bluebird');
var connection = Promise.promisifyAll(box.getConnection(req.user.login));
connection.ready(function() {
connection.getFolderItemsAsync(0, null).then(function(result) {
return Promise.map(result.entries, function(item) {
return connection.getFileInfoAsync(item.id).catch(function(err){
// post the results as null and continue with the other results
return null;
});
})
}).then(function(results) {
// array of results here (some might be null if they had an error)
}, function(err) {
// error here
});
});
thủ Coded Version
Dưới đây là một phiên bản bằng tay được mã hóa. Chìa khóa cho điều này là phát hiện khi vòng lặp không đồng bộ của bạn được thực hiện bằng cách so sánh if (results.length === result.entries.length)
. Lưu ý: Điều này có xử lý lỗi không đầy đủ, đó là một trong những khó khăn của việc mã hóa điều này bằng tay và không sử dụng khung công tác không đồng bộ như lời hứa.
var connection = box.getConnection(req.user.login);
connection.ready(function() {
connection.getFolderItems(0, null, function (err, result) {
if (err) {
// do error handling here
opts.body = err;
} else {
var results = [];
for (var i = 0; i < result.entries.length; i++) {
connection.getFileInfo(result.entries[i].id, function (err, fileInfo) {
if (err) {
// do error handling here
opts.body = err;
results.push(null);
} else {
results.push(fileInfo);
}
// if done with all requests
if (results.length === result.entries.length) {
// done with everything, results are in results
// process final results here
}
});
}
}
});
});
Tất cả các câu trả lời tôi nhận được là tuyệt vời - cảm ơn bạn! Tôi vết thương bằng cách sử dụng async, như bạn và JasonWihardja đề nghị. Đây là một hướng dẫn tốt: http://justinklemm.com/node-js-async-tutorial/ – paulsm4
Tôi vẫn nghĩ rằng hứa hẹn cuối cùng là cách thành ngữ hơn để làm điều này, nhưng tôi vui vì bạn thấy nó hữu ích. – skarface