p-limit

node v10.24.1
version: 1.0.0
endpointsharetweet
const pTry = require('p-try'); const pLimit = concurrency => { if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) { return Promise.reject(new TypeError('Expected `concurrency` to be a number from 1 and up')); } const queue = []; let activeCount = 0; const next = () => { activeCount--; if (queue.length > 0) { queue.shift()(); } }; const run = async (fn, resolve, ...args) => { activeCount++; // TODO: Get rid of `pTry`. It's not needed anymore. const result = pTry(fn, ...args); resolve(result); try { await result; } catch(e) { console.log(e) } next(); }; const enqueue = (fn, resolve, ...args) => { queue.push(run.bind(null, fn, resolve, ...args)); (async () => { // This function needs to wait until the next microtask before comparing // `activeCount` to `concurrency`, because `activeCount` is updated asynchronously // when the run function is dequeued and called. The comparison in the if-statement // needs to happen asynchronously as well to get an up-to-date value for `activeCount`. await Promise.resolve(); if (activeCount < concurrency && queue.length > 0) { queue.shift()(); } })(); }; const generator = (fn, ...args) => new Promise(resolve => enqueue(fn, resolve, ...args)); Object.defineProperties(generator, { activeCount: { get: () => activeCount }, pendingCount: { get: () => queue.length }, clearQueue: { value: () => { queue.length = 0; } } }); return generator; }; const results = []; const timeout = i => new Promise(resolve => setTimeout(() => { results.push(i); resolve(i); }, i) ) const limit = pLimit(2); (async () => { // Only one promise is run at once const result = await Promise.all([ limit(() => timeout(100)), limit(() => timeout(500)), limit(() => timeout(300)), limit(() => timeout(200)), ]); console.log(result); })();
Loading…

no comments

    sign in to comment