【问题标题】:implement a promise to return the slower of two promises实现一个承诺以返回两个承诺中较慢的一个
【发布时间】:2020-06-13 22:03:20
【问题描述】:

我是异步编程的新手,我只是熟悉用 Promise 代替回调的想法。 我正在尝试实现一个函数(promise)来接受另外两个promise,并且只有在两个promise 都完成的情况下才会返回一个需要更长时间才能完成的promise 的值。 所以基本上我的想法是使用 Date.now() 函数来计算执行一个承诺所需的时间,但是我很难把它写下来,特别是一个包含其他两个承诺的承诺(如果那是什可能),这是我的尝试:

var p1 = new Promise((resolve, reject) => {
let start = Date.now();
setTimeout(() => 
   resolve(
     {
       id: 0,
       time: Date.now() - start,
       value: 4+3
     }
           ), 500);
})

var p2 = new Promise((resolve, reject) => {
  let start = Date.now();

  setTimeout(() => 
    reject(
      {
        id: 1,
        time: Date.now() - start,
        value: 7+3
      }
          ), 800);
})

这只是一个想法,promise p1, p2 应该作为 promise 'slower' 的参数给出,我对 Date.now() 所做的事情应该以某种方式围绕对这些 Promise 的调用,然后我希望计算两个 Promise 的运行时间,然后返回较慢的 Promise 的值。 关于如何实现这一点的任何想法?谢谢。

【问题讨论】:

    标签: es6-promise asynchronous-javascript


    【解决方案1】:

    这里有一个关于如何做到这一点的想法。而不是时间戳,我只使用了cntr。最后一个(最慢的)将被标记为cntr === 0,所以当它们都完成后,我们就可以对标记有0 cntr 的那个进行处理并返回它的val。

    function promiseSlowAll(arrayOfPromises) {
        let cntr = arrayOfPromises.length - 1;
        let newPromises = arrayOfPromises.map(p => {
            return p.then(val => {
                // wrap the results in an object along with a cntr
                return {val: val, cntr: cntr--};
            });
        });
        return Promise.all(newPromises).then(allResults => {
            const lastResult = allResults.find(item => item.cntr === 0);
            // resolve with a single result from the last promise to finish
            return lastResult.val;
        });
    }
    

    因此,您使用一组 promise 调用 promiseSlowAll(),然后返回一个已解析的值,该值对应于最慢的 promise 解析。

    这是一个工作演示:

    function promiseSlowAll(arrayOfPromises) {
        let cntr = arrayOfPromises.length - 1;
        let newPromises = arrayOfPromises.map(p => {
            return p.then(val => {
                // wrap the results in an object along with a cntr
                return {val: val, cntr: cntr--};
            });
        });
        return Promise.all(newPromises).then(allResults => {
            const lastResult = allResults.find(item => item.cntr === 0);
            return lastResult.val;
        });
    }
    
    function delay(t, v) {
        return new Promise(resolve => {
            setTimeout(resolve, t, v);
        });
    }
    
    promiseSlowAll([delay(200, "200"), delay(300, "300"), delay(100, "100")]).then(r => {
        console.log("slowest is", r);
    });

    【讨论】:

    • 因此,promise 在数组中的顺序无关紧要?因为它看起来确实如此,所以看起来数组中的最后一个承诺将获得 cntr = 0。
    • @sadElephent - 不,原始数组中的顺序在这里无关紧要。请记住,promise 会按照它们自己的顺序解决。因此,p.then() 在 promise 解决时被调用,而不是按照它们出现在数组中的顺序,这就是分配 cntr 的地方。因此,解决并调用它的最后一个承诺是.then() 处理程序,得到cntr === 0。试试演示。中间那个最慢,最后是cntr === 0。将副本复制到您自己的文件中,并尝试不同的命令来证明给自己看。
    • 谢谢!我想让我失望的是你正在使用地图这一事实,我认为它会以正确的顺序解决承诺。可以肯定的是,会发生什么是 map 同步执行,因此所有这些实际上是同时发生的,重要的是 then() 的调用顺序是什么,因为这是计数器设置正确的地方?
    • @sadElephent - 所有.map() 所做的只是注册.then() 处理程序并从每次调用.then() 创建一个新的承诺。调用.then() 只是注册新的事件处理程序,然后当主机承诺解决时,在.map() 完成很久之后,将调用这些事件处理程序。 .map() 是同步的,但它所做的只是注册一堆事件处理程序。这些事件处理程序将在稍后按每个 Promise 解决的顺序(无论是什么顺序)调用。
    • 如果我想在返回之前确保所有的承诺都得到了解决怎么办?我该怎么办?
    猜你喜欢
    • 2015-11-27
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    相关资源
    最近更新 更多