İşte bir kopyala-yapıştır dostu ve eşzamanlılık sınırı olan eksiksiz Promise.all()
/ map()
alternatif özellikli ES7 çözümüm .
Buna benzer şekilde Promise.all()
, iade emrini ve taahhüt dışı dönüş değerleri için bir geri dönüşü korur.
Ayrıca, diğer çözümlerden birkaçının kaçırdığı bazı yönleri gösterdiği için farklı uygulamaların bir karşılaştırmasını da dahil ettim.
Kullanım
const asyncFn = delay => new Promise(resolve => setTimeout(() => resolve(), delay));
const args = [30, 20, 15, 10];
await asyncPool(args, arg => asyncFn(arg), 4);
Uygulama
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();
});
}
Karşılaştırma
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);
Sonuç
asyncPool()
Yeni isteklerin önceki istek biter bitmez başlamasına izin verdiği için en iyi çözüm olmalıdır.
asyncBatch()
uygulaması anlaşılması daha kolay olduğu için karşılaştırma olarak dahil edilmiştir, ancak bir sonraki partiyi başlatmak için aynı partideki tüm isteklerin tamamlanması gerektiğinden performans açısından daha yavaş olmalıdır.
Bu uydurma örnekte, sınırlı olmayan vanilya Promise.all()
elbette en hızlısıdır, diğerleri ise gerçek dünyadaki tıkanıklık senaryosunda daha arzu edilir bir performans sergileyebilir.
Güncelleme
Başkalarının zaten önerdiği zaman uyumsuz havuz kitaplığı, neredeyse aynı şekilde çalıştığı ve Promise.race () 'nin akıllıca kullanımıyla daha kısa bir uygulamaya sahip olduğu için muhtemelen benim uygulamama daha iyi bir alternatiftir: https://github.com/rxaviers/ async-pool / blob / master / lib / es7.js
Umarım cevabım hala eğitimsel bir değere hizmet edebilir.