Promise.allSettled with timing for each call

huangapple go评论65阅读模式
英文:

Promise.allSettled with timing for each call

问题

有没有一种技术或JavaScript库可以有效地执行等效于 Promises.allSettled([任务数组]); 并访问每个任务花费的毫秒数的操作?

例如,如果我同时发起了5个远程API调用,我想知道是否值得将它们分成两个单独的调用来处理快速加载的任务,而慢加载的任务仍在加载中。如果它们都大致需要相同的加载时间,那就不值得这样做。

英文:

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.

答案1

得分: 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)
})();
英文:

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.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

(async () =&gt; {
  console.log(&#39;This will take up to 5 seconds to complete&#39;)

  const tasks = Array.from({length: 3}, (_,i) =&gt;
    new Promise(resolve =&gt; 
      setTimeout(() =&gt; resolve(`task ${i} result`), Math.random()*5000|0))
  )
  
  const timeTask = async (task, startMs = Date.now()) =&gt; 
    ({value: await task, duration: Date.now() - startMs})

  let results = await Promise.allSettled(tasks.map(t =&gt; timeTask(t)))

  console.log(results)
})();

<!-- end snippet -->

答案2

得分: 1

以下是翻译好的代码部分:

// 您可以拦截所有承诺的完成并记录每个完成所花费的时间,同时仍将它们传递给`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`);
        });
    }));
}

// 或者,如果您希望计时结果嵌入到`Promise.allSettled()`的结果中,可以这样做:

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 => {
        // 将时间传递到结果数组
        for (let i = 0; i < results.length; i++) {
            results[i].time = times[i];
        }
        return results;
    });
}

// 注意:此实现假设您传递了一个数组(以便它可以使用`.map()`),如果有必要,它可以接受任意可迭代对象的稍微多一点的代码。

请注意,这是您提供的代码的中文翻译,没有其他内容。

英文:

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) =&gt; {
        return p.finally(() =&gt; {
            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) =&gt; {
        return p.finally(() =&gt; {
            times[index] = Date.now() - start;
        });
    })).then(results =&gt; {
        // transfer times over to the result array
        for (let i = 0; i &lt; 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.

huangapple
  • 本文由 发表于 2023年6月12日 11:53:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76453553.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定