Search code examples
limites6-promise

How to use the limit.pendingCount variable in p-limit?


I am using p-limit package to limit the # of concurrent requests made using Promise.all.

I would like to show the progress of the total requests, and see that there is a variable limit.pendingCount in the library.

My question is how can I use that variable to report progress, when I console log that variable, it only returns a final value of 0.

(async () => {
       const result = await Promise.all(promises);

       // eslint-disable-next-line
          console.log(limit.pendingCount);

Solution

  • Since you are await-ing the Promise.all call, all promises will be completed by the time you reach your console.log statement.

    Try checking the pending count without await-ing the promises initially. Any code after await-ing the promises will only be executed after all promises are completed (i.e. pending count is 0).

    const numThreads = 2;
    const numPromises = 4;
    
    const pLimit = require("p-limit")
    const limit = pLimit(numThreads);
    const promises = new Array(numPromises).fill()
        .map((n, i) => i + 1)
        .map(n => limit(() => new Promise(r => {
                console.log(`Started Promise ${n}`);
                setTimeout(r, n * 1000);
            })
            .then(() => console.log(`Completed Promise ${n}`))));
    trackProgress('After Promises Initiated', promises);
    const result = await Promise.all(promises);
    trackProgress('After Promises Awaited', promises);
    
    /**
     * Prints the state of the current pending promises until all pending promises are completed. This works only for this sample; it is not production quality.
     */
    function trackProgress(label, promises) {
        console.log(`[${label}] Tracking started.`);
        const printProgress = () => {
            if (limit.pendingCount > 0) {
                console.log(`[${label}] Pending: ${limit.pendingCount} of ${promises.length}`);
                setTimeout(printProgress, 1000);
            }
            else {
                console.log(`[${label}] Tracking completed.`);
            }
        };
        printProgress();    
    }
    
    /*
     * Output:
     * "Started Promise 1"
     * "Started Promise 2"
     * "[After Promises Initiated] Tracking started."
     * "[After Promises Initiated] Pending: 2 of 4"
     * "Completed Promise 1"
     * "Started Promise 3"
     * "[After Promises Initiated] Pending: 1 of 4"
     * "Completed Promise 2"
     * "Started Promise 4"
     * "[After Promises Initiated] Tracking completed."
     * "Completed Promise 3"
     * "Completed Promise 4"
     * "[After Promises Awaited] Tracking started."
     * "[After Promises Awaited] Tracking completed."
     */
    

    Edit:

    If you are looking to do a progress tracker, you may have better luck by adding callbacks to the end of the executed promises:

    const numThreads = 2;
    const numPromises = 4;
    
    const pLimit = require("p-limit");
    function executeRequests() {
        const limit = pLimit(numThreads);
        let numCompleted = 0;
        console.log(`${100 * numCompleted / numPromises}% Complete`);
        const updateNumCompleted = () => {
            numCompleted++;
            // TODO: Instead of console.log, update UI
            console.log(`${100 * numCompleted / numPromises}% Complete`);
            if (numCompleted >= numPromises) {
                // TODO: Instead of console.log, update UI
                console.log('All promises complete');
            }
        };
        const promises = new Array(numPromises).fill()
            .map((n, i) => i + 1)
            .map(n => limit(() => new Promise(r => {
                    console.log(`Started Promise ${n}`);
                    setTimeout(r, n * 1000);
                })
                .then(() => {
                    console.log(`Completed Promise ${n}`);
                    updateNumCompleted();
                })));
        Promise.all(promises);
    }
    executeRequests();
    
    /*
     * Output:
     * "0% Complete"
     * "Started Promise 1"
     * "Started Promise 2"
     * "Completed Promise 1"
     * "25% Complete"
     * "Started Promise 3"
     * "Completed Promise 2"
     * "50% Complete"
     * "Started Promise 4"
     * "Completed Promise 3"
     * "75% Complete"
     * "Completed Promise 4"
     * "100% Complete"
     * "All promises complete"
     */