บนพื้นฐานของชื่อคำถาม "แก้ไขสัญญาหลังจากนั้นอีกหนึ่ง (เช่นในลำดับ)?" เราอาจเข้าใจว่า OP มีความสนใจในการจัดการลำดับของสัญญาในการชำระมากกว่าการโทรตามลำดับต่อเนื่องse
คำตอบนี้มีให้:
- เพื่อแสดงให้เห็นว่าการโทรตามลำดับนั้นไม่จำเป็นสำหรับการจัดการการตอบสนองตามลำดับ
- เพื่อแสดงรูปแบบทางเลือกที่ทำงานได้กับผู้เข้าชมหน้านี้รวมถึง OP หากเขายังสนใจในอีกหนึ่งปีต่อมา
- แม้จะมีการยืนยันของ OP ว่าเขาไม่ต้องการโทรออกไปพร้อม ๆ กันซึ่งอาจเป็นกรณีจริง ๆ แต่อย่างเท่าเทียมกันอาจเป็นข้อสมมุติบนพื้นฐานของความปรารถนาที่จะจัดการกับการตอบสนองตามลำดับเมื่อชื่อมีความหมาย
หากไม่ต้องการการโทรพร้อมกันอย่างแท้จริงโปรดดูคำตอบของ Benjamin Gruenbaum ซึ่งครอบคลุมการโทรตามลำดับ (ฯลฯ ) อย่างครอบคลุม
หากคุณสนใจ (เพื่อประสิทธิภาพที่ดีขึ้น) ในรูปแบบที่อนุญาตให้มีการโทรพร้อมกันตามด้วยการจัดการการตอบสนองตามลำดับโปรดอ่านต่อไป
มันน่าดึงดูดที่คิดว่าคุณต้องใช้Promise.all(arr.map(fn)).then(fn)
(เท่าที่ฉันทำมาหลายครั้ง) หรือน้ำตาลแฟนซีของ Promise lib (โดยเฉพาะอย่างยิ่ง Bluebird's) อย่างไรก็ตาม (มีเครดิตในบทความนี้ ) arr.map(fn).reduce(fn)
รูปแบบจะทำงานได้โดยมีข้อดีที่:
- ทำงานร่วมกับ lib สัญญาใด ๆ - แม้รุ่น jQuery ที่ตรงตาม - เท่านั้น
.then()
จะถูกใช้
- กำบังความยืดหยุ่นในการข้ามข้อผิดพลาดหรือหยุดข้อผิดพลาดแล้วแต่ว่าคุณต้องการด้วยโมเดอเรเตอร์ใดบรรทัดหนึ่ง
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.
});
};
หมายเหตุ: มีเพียงส่วนเดียวเท่านั้น Q()
แฟรกเมนต์เป็นค่าเฉพาะสำหรับ Q สำหรับ jQuery คุณต้องแน่ใจว่า readFile () ส่งคืนสัญญา jQuery ด้วย A + libs สัญญาต่างประเทศจะถูกหลอมรวม
ที่สำคัญนี่คือการลดของsequence
สัญญาซึ่งลำดับการจัดการของreadFile
สัญญา แต่ไม่สร้างของพวกเขา
และเมื่อคุณหมกมุ่นกับมันมันอาจจะเหลือเชื่อเมื่อคุณรู้ว่า.map()
เวทีนั้นไม่จำเป็นจริงๆ! งานทั้งหมด, การโทรแบบขนานและการจัดการแบบอนุกรมในลำดับที่ถูกต้อง, สามารถทำได้โดยreduce()
ลำพัง, รวมถึงข้อดีเพิ่มเติมของความยืดหยุ่นเพิ่มเติมเพื่อ
- แปลงจากการโทรแบบขนาน async เป็นการโทรแบบอนุกรม async เพียงแค่เคลื่อนย้ายหนึ่งบรรทัด - อาจเป็นประโยชน์ในระหว่างการพัฒนา
ที่นี่มันเป็นQ
อีกครั้ง
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.
});
};
นั่นเป็นรูปแบบพื้นฐาน หากคุณต้องการส่งข้อมูล (เช่นไฟล์หรือการแปลงบางส่วน) ไปยังผู้โทรคุณจะต้องมีตัวแปรที่ไม่รุนแรง