นี่คือโซลูชัน ES7 ของฉันสำหรับการคัดลอกและคุณสมบัติที่สมบูรณ์Promise.all()
/ map()
ทางเลือกที่มีขีด จำกัด การทำงานพร้อมกัน
ในทำนองเดียวกันจะPromise.all()
รักษาคำสั่งคืนสินค้าเช่นเดียวกับทางเลือกสำหรับค่าการส่งคืนที่ไม่ใช่สัญญา
ฉันยังรวมการเปรียบเทียบการใช้งานที่แตกต่างกันเนื่องจากแสดงให้เห็นถึงแง่มุมบางประการที่โซลูชันอื่น ๆ บางส่วนพลาดไป
การใช้งาน
const asyncFn = delay => new Promise(resolve => setTimeout(() => resolve(), delay));
const args = [30, 20, 15, 10];
await asyncPool(args, arg => asyncFn(arg), 4);
การนำไปใช้
async function asyncBatch(args, fn, limit = 8) {
args = [...args];
const outs = [];
while (args.length) {
const batch = args.splice(0, limit);
const out = await Promise.all(batch.map(fn));
outs.push(...out);
}
return outs;
}
async function asyncPool(args, fn, limit = 8) {
return new Promise((resolve) => {
const argQueue = [...args].reverse();
let count = 0;
const outs = [];
const pollNext = () => {
if (argQueue.length === 0 && count === 0) {
resolve(outs);
} else {
while (count < limit && argQueue.length) {
const index = args.length - argQueue.length;
const arg = argQueue.pop();
count += 1;
const out = fn(arg);
const processOut = (out, index) => {
outs[index] = out;
count -= 1;
pollNext();
};
if (typeof out === 'object' && out.then) {
out.then(out => processOut(out, index));
} else {
processOut(out, index);
}
}
}
};
pollNext();
});
}
การเปรียบเทียบ
const asyncFn = delay => new Promise(resolve => setTimeout(() => {
console.log(delay);
resolve(delay);
}, delay));
const args = [30, 20, 15, 10];
const out1 = await Promise.all(args.map(arg => asyncFn(arg)));
const out2 = await asyncPool(args, arg => asyncFn(arg), 2);
const out3 = await asyncBatch(args, arg => asyncFn(arg), 2);
console.log(out1, out2, out3);
สรุป
asyncPool()
ควรเป็นทางออกที่ดีที่สุดเนื่องจากช่วยให้คำขอใหม่เริ่มต้นได้ทันทีที่คำขอก่อนหน้านี้เสร็จสิ้น
asyncBatch()
รวมอยู่ในการเปรียบเทียบเนื่องจากการนำไปใช้งานนั้นเข้าใจง่ายกว่า แต่ควรมีประสิทธิภาพช้าลงเนื่องจากคำขอทั้งหมดในชุดงานเดียวกันจำเป็นต้องดำเนินการให้เสร็จสิ้นเพื่อเริ่มชุดต่อไป
ในตัวอย่างที่สร้างขึ้นนี้วานิลลาไม่ จำกัด Promise.all()
แน่นอนว่านั้นเร็วที่สุดในขณะที่ชนิดอื่น ๆ สามารถทำงานได้เป็นที่ต้องการมากกว่าในสถานการณ์ความแออัดในโลกแห่งความเป็นจริง
อัปเดต
ไลบรารี async-pool ที่คนอื่นแนะนำไปแล้วน่าจะเป็นทางเลือกที่ดีกว่าสำหรับการใช้งานของฉันเนื่องจากทำงานได้เกือบเหมือนกันและมีการใช้งานที่รัดกุมยิ่งขึ้นด้วยการใช้ Promise.race () อย่างชาญฉลาด: https://github.com/rxaviers/ async-pool / blob / master / lib / es7.js
หวังว่าคำตอบของฉันจะยังคงให้คุณค่าทางการศึกษา