skip to Main Content

Is there a technique or javascript library to effectively perform the equivalent of Promises.allSettled([Array of tasks]); and access the number of milliseconds each task took?

For example, if I make 5 concurrent API calls to remote services, I’d like to see if it would be worth grouping them into two separate calls to process the fast ones while the slow ones are still loading. If they all take around the same amount of time to load, it wouldn’t be worth the effort.

2

Answers


  1. You can write a simple wrapper to time each task, and return both the result of each task and its duration.

    This code creates 3 tasks, each of which delay for a random duration between 0 and 5 seconds. We wrap each task using the timeTask function. The duration is measured in milliseconds.

    (async () => {
      console.log('This will take up to 5 seconds to complete')
    
      const tasks = Array.from({length: 3}, (_,i) =>
        new Promise(resolve => 
          setTimeout(() => resolve(`task ${i} result`), Math.random()*5000|0))
      )
      
      const timeTask = async (task, startMs = Date.now()) => 
        ({value: await task, duration: Date.now() - startMs})
    
      let results = await Promise.allSettled(tasks.map(t => timeTask(t)))
    
      console.log(results)
    })();
    Login or Signup to reply.
  2. You can just intercept the completion of all the promises and record the time for each while still passing them to Promise.allSettled()

    function allSettledTimed(promises) {
        const start = Date.now();
        return Promise.allSettled(promises.map((p, index) => {
            return p.finally(() => {
                console.log(`[${index}] took ${Date.now() - start}ms to complete`);
            });
        }));
    }
    

    Or, if you want the timing results to be embedded into the Promise.allSettled() results, you can do that like this:

    function allSettledTimed(promises) {
        const start = Date.now();
        const times = new Array(promises.length);
        return Promise.allSettled(promises.map((p, index) => {
            return p.finally(() => {
                times[index] = Date.now() - start;
            });
        })).then(results => {
            // transfer times over to the result array
            for (let i = 0; i < results.length; i++) {
                results[i].time = times[i];
            }
            return results;
        });
    }
    

    Note: This implementation assumes you passed an array (so it can use .map()), not an arbitrary iterable. With a little more code, it could accept an arbitrary iterable if that was necessary.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search