Trên cơ sở các tiêu đề của câu hỏi, "lời hứa Giải quyết cái khác (ví dụ: theo thứ tự)?", Chúng ta có thể hiểu rằng OP là quan tâm nhiều hơn trong việc xử lý tuần tự những lời hứa về giải quyết hơn các cuộc gọi liên tục cho mỗi gia nhập .
Câu trả lời này được cung cấp:
- để chứng minh rằng các cuộc gọi tuần tự là không cần thiết để xử lý tuần tự các phản hồi.
- để hiển thị các mẫu thay thế khả thi cho khách truy cập của trang này - bao gồm cả OP nếu anh ta vẫn quan tâm hơn một năm sau đó.
- mặc dù OP khẳng định rằng anh ta không muốn thực hiện các cuộc gọi đồng thời, điều này thực sự có thể là trường hợp nhưng cũng có thể là một giả định dựa trên mong muốn xử lý tuần tự các câu trả lời như tiêu đề.
Nếu các cuộc gọi đồng thời thực sự không muốn thì hãy xem câu trả lời của Benjamin Gruenbaum bao gồm các cuộc gọi liên tiếp (vv) một cách toàn diện.
Tuy nhiên, nếu bạn quan tâm (để cải thiện hiệu suất) trong các mẫu cho phép các cuộc gọi đồng thời theo sau là xử lý tuần tự các phản hồi, thì vui lòng đọc tiếp.
Thật hấp dẫn khi nghĩ rằng bạn phải sử dụng Promise.all(arr.map(fn)).then(fn)
(như tôi đã thực hiện nhiều lần) hoặc một loại đường ưa thích của Promise lib (đặc biệt là của Bluebird), tuy nhiên (với tín dụng cho bài viết này ), một arr.map(fn).reduce(fn)
mô hình sẽ thực hiện công việc, với những ưu điểm của nó:
- hoạt động với bất kỳ lời hứa lib nào - ngay cả các phiên bản jQuery tuân thủ trước - chỉ
.then()
được sử dụng.
- Có tính linh hoạt để bỏ qua lỗi hoặc dừng lỗi, bất cứ khi nào bạn muốn với một mod dòng.
Đây là, viết cho Q
.
var readFiles = function(files) {
return files.map(readFile) //Make calls in parallel.
.reduce(function(sequence, filePromise) {
return sequence.then(function() {
return filePromise;
}).then(function(file) {
//Do stuff with file ... in the correct sequence!
}, function(error) {
console.log(error); //optional
return sequence;//skip-over-error. To stop-on-error, `return error` (jQuery), or `throw error` (Promises/A+).
});
}, Q()).then(function() {
// all done.
});
};
Lưu ý: chỉ có một đoạn đó, Q()
dành riêng cho Q. Đối với jQuery, bạn cần đảm bảo rằng readFile () trả về một lời hứa jQuery. Với A + libs, những lời hứa nước ngoài sẽ được đồng hóa.
Chìa khóa ở đây là của giảm sequence
lời hứa, mà trình tự các xử lý củareadFile
lời hứa nhưng không phải là sự sáng tạo của họ.
Và một khi bạn đã hấp thụ điều đó, có lẽ hơi khó chịu khi bạn nhận ra rằng .map()
sân khấu không thực sự cần thiết! Toàn bộ công việc, các cuộc gọi song song cộng với xử lý nối tiếp theo đúng thứ tự, có thể đạt được reduce()
một mình, cộng với lợi thế tăng thêm tính linh hoạt để:
- chuyển đổi từ các cuộc gọi async song song sang các cuộc gọi async nối tiếp bằng cách di chuyển một dòng - có khả năng hữu ích trong quá trình phát triển.
Đây là, cho Q
một lần nữa.
var readFiles = function(files) {
return files.reduce(function(sequence, f) {
var filePromise = readFile(f);//Make calls in parallel. To call sequentially, move this line down one.
return sequence.then(function() {
return filePromise;
}).then(function(file) {
//Do stuff with file ... in the correct sequence!
}, function(error) {
console.log(error); //optional
return sequence;//Skip over any errors. To stop-on-error, `return error` (jQuery), or `throw error` (Promises/A+).
});
}, Q()).then(function() {
// all done.
});
};
Đó là mô hình cơ bản. Nếu bạn cũng muốn cung cấp dữ liệu (ví dụ: các tệp hoặc một số biến đổi của chúng) cho người gọi, bạn sẽ cần một biến thể nhẹ.