Array.forEach
ไม่ได้ให้สิ่งที่ดี (ถ้ามี) แต่มีหลายวิธีในการบรรลุสิ่งที่คุณต้องการ:
ใช้เคาน์เตอร์ง่าย ๆ
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
(ขอบคุณ @vanuan และคนอื่น ๆ ) วิธีการนี้รับประกันว่ารายการทั้งหมดจะได้รับการประมวลผลก่อนที่จะเรียกกลับ "เสร็จสิ้น" คุณต้องใช้ตัวนับที่ได้รับการอัพเดตในการติดต่อกลับ ทั้งนี้ขึ้นอยู่กับค่าของพารามิเตอร์ดัชนีไม่ได้ให้การรับประกันเดียวกันเนื่องจากลำดับของการส่งคืนของการดำเนินการแบบอะซิงโครนัสไม่ได้รับประกัน
ใช้สัญญา ES6
(ห้องสมุดสัญญาสามารถใช้กับเบราว์เซอร์รุ่นเก่า):
ประมวลผลคำขอทั้งหมดที่รับประกันการดำเนินการแบบซิงโครนัส (เช่น 1 จาก 2 และ 3)
function asyncFunction (item, cb) {
setTimeout(() => {
console.log('done with', item);
cb();
}, 100);
}
let requests = [1, 2, 3].reduce((promiseChain, item) => {
return promiseChain.then(() => new Promise((resolve) => {
asyncFunction(item, resolve);
}));
}, Promise.resolve());
requests.then(() => console.log('done'))
ประมวลผลคำขอ async ทั้งหมดโดยไม่ต้องดำเนินการ "ซิงโครนัส" (2 อาจเสร็จเร็วกว่า 1)
let requests = [1,2,3].map((item) => {
return new Promise((resolve) => {
asyncFunction(item, resolve);
});
})
Promise.all(requests).then(() => console.log('done'));
ใช้ไลบรารี async
มีไลบรารีแบบอะซิงโครนัสอื่น ๆ asyncเป็นที่นิยมมากที่สุดที่ให้กลไกที่จะแสดงสิ่งที่คุณต้องการ
แก้ไข
เนื้อความของคำถามได้รับการแก้ไขเพื่อลบรหัสตัวอย่างก่อนหน้านี้ซิงโครนัสดังนั้นฉันจึงได้อัปเดตคำตอบของฉันเพื่อชี้แจง ตัวอย่างดั้งเดิมที่ใช้ซิงโครนัสเช่นรหัสเพื่อจำลองพฤติกรรมแบบอะซิงโครนัสดังนั้นจึงมีการนำไปใช้ดังต่อไปนี้:
array.forEach
เป็นแบบซิงโครนัสและเป็นres.write
เช่นนั้นดังนั้นคุณสามารถเพียงแค่โทรกลับหลังจากที่คุณโทรไปที่หน้า:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
วิธีอาร์เรย์มาตรฐานมีdone
พารามิเตอร์allDone
โทรกลับและโทรกลับ!