यहाँ मेरा 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()
बेशक सबसे तेज है, जबकि अन्य वास्तविक दुनिया की भीड़ के परिदृश्य में अधिक वांछनीय प्रदर्शन कर सकते हैं।
अपडेट करें
एसिंक्स-पूल लाइब्रेरी जो दूसरों ने पहले ही सुझाई है, शायद मेरे कार्यान्वयन का एक बेहतर विकल्प है क्योंकि यह लगभग समान रूप से काम करती है और इसमें Promise.race के चतुर उपयोग के साथ अधिक संक्षिप्त कार्यान्वयन है (): https://github.com/rxaviers/ async-पूल / ब्लॉब / मास्टर / lib / es7.js
उम्मीद है कि मेरा जवाब अभी भी एक शैक्षिक मूल्य परोस सकता है।