【问题标题】:Promise.all get slowest resolving promisesPromise.all 得到最慢的解决承诺
【发布时间】:2021-04-17 23:44:56
【问题描述】:

我有数百个东西要在 html5 画布中并行渲染。这些在Promise.all 调用中并行绘制。现在,我想知道这些承诺中的哪一个是最后被解决的。


// get a promise that will resolve in between 0 and 5 seconds.
function resolveAfterSomeTime(): Promise<void> {
    return new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
}

const myPromises = [];
for (let i = 0; i < 100; i++) {
    myPromises.push(resolveAfterSomeTime);
}

Promise.all(myPromises).then(() => {
    // find out which promise was the last to resolve.
})

就我而言,我有多个类,每个类都有一个 render() 函数。其中一些比其他重,但我想知道哪些。

我有一些类似的东西,我想知道哪个承诺最慢解决,以便我可以优化它。

【问题讨论】:

  • 您是否希望在 Promise 执行期间进行优化?

标签: javascript typescript promise promise.all


【解决方案1】:

这是每个承诺在解析后设置lastPromiseToResolve 的值的一种方式。最后一个要解决的承诺会将其设置为最后。


// get a promise that will resolve in between 0 and 5 seconds.
function resolveAfterSomeTime(): Promise<void> {
    return new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
}

let lastPromiseToResolve = null
const myPromises = [];
for (let i = 0; i < 100; i++) {
    const promise = resolveAfterSomeTime()
    myPromises.push(promise.then(() => {
        lastPromiseToResolve = promise // all the promises will set lastPromiseToResolve
    }));
}

Promise.all(myPromises).then(() => {
  console.log(lastPromiseToResolve) // this would be the last promise to resolve
})

【讨论】:

    【解决方案2】:

    我能想到的最好方法是使用一个计数器来指示到目前为止已解决的承诺数量:

    function resolveAfterSomeTime() {
      return new Promise((resolve) => setTimeout(resolve, Math.random() * 5000));
    }
    
    const myPromises = [];
    let resolveCount = 0;
    for (let i = 0; i < 100; i++) {
      myPromises.push(
        resolveAfterSomeTime()
          .then(() => {
            resolveCount++;
            if (resolveCount === 100) {
              console.log('all resolved');
              console.log('array item', i, 'took longest');
            }
          })
      );
    }

    【讨论】:

      【解决方案3】:

      你可以为每个承诺计时。如果您想具体了解哪个正在解析,您甚至可以为每个标识符分配一个标识符。下面的timePromise 函数接受一个id 和一个返回promise 的函数,该promise 的时间,并记录结果。它不会改变 promise 的结果,所以你可以像往常一样使用myPromises

      function resolveAfterSomeTime() {
          return new Promise((resolve) => setTimeout(resolve, Math.random() * 1000));
      }
      
      // f is a function that returns a promise
      function timePromise(id, f) {
        const start = Date.now()
        
        return f()
          .then(x => {
            const stop = Date.now()
            
            console.log({id, start, stop, duration: (stop - start)})
            return x
          })
      }
      
      const myPromises = [];
      for (let i = 0; i < 100; i++) {
          myPromises.push(timePromise(i, resolveAfterSomeTime));
      }
      
      Promise.all(myPromises).then(() => {
          // find out which promise was the last to resolve.
      })

      我不确定您是如何在实际代码中创建承诺数组的,因此将每个承诺包装在返回它的函数中可能并不简单。但您可能会根据您的情况调整它。

      如果您不关心确切知道每个需要多长时间,您可以让timePromise 接受一个已经开始的承诺,以及从调用timePromise 到它解决的时间。这不会那么准确,但仍会给您一个大致的概念,尤其是当一个或几个承诺比其他承诺花费更长的时间时。

      类似这样的:

      function timePromise(id, p) {
        const start = Date.now()
        
        return p
          .then(x => {
            const stop = Date.now()
            
            console.log({id, start, stop, duration: (stop - start)})
            return x
          })
      }
      
      const myPromises = [];
      for (let i = 0; i < 100; i++) {
          myPromises.push(timePromise(i, resolveAfterSomeTime()));
      }
      

      【讨论】:

      • 很有趣,但是由于所有的 Promise 都是并行运行的,所以需要多长时间并不重要。重要的是最慢的需要多长时间。
      • 您说要优化最慢的那个。如果它们都花费相同的时间怎么办?或者如果多个承诺需要很长时间怎么办?如果您只知道最慢的承诺,您可能会浪费时间优化它,即使它花费的时间与所有其他承诺大致相同,或者您可能会错过需要优化多个承诺。通过这种方式,您将了解究竟是什么导致了较长的渲染时间。
      • 如果您想知道哪个最后完成,只需查看最后一条日志消息 :)
      • 例如,如果你有 5 个 promise,它们的运行时间以毫秒为单位:[10, 10, 10, 4900, 5000]。您实际上希望优化最后两个。或者如果这些是它们的运行时:[100、101、102、103、104]。优化最后一个并不会真正获得太多收益,因为所有其他的运行速度都一样快/慢。
      • @MarcheRemi 哎呀,忘记在 ^^^ 中标记你
      猜你喜欢
      • 2022-08-20
      • 1970-01-01
      • 2021-12-20
      • 2022-01-16
      • 2023-01-21
      • 1970-01-01
      • 2019-09-29
      • 2020-10-17
      • 2021-02-02
      相关资源
      最近更新 更多