如何推送到Promise.all(数组)

时间:2017-11-13 23:56:39

标签: javascript promise

我不认为这可以通过本机承诺实现,但这是我想要的基本概念:

const promises = [
    getSomething(),
    getSomethingElse(),
];

// combine promises
const alldone = Promise.all(promises);

// Add a promise after the previous ones have started
promises.push(getAThirdThing());

// everything, including `getAThirdThing` is done
await allDone;

实际上Promise.all()并不关心我将某些内容推到promises数组上。

是否有类似的模式可以完成同样的事情?具体来说,添加其他承诺等待,因为它们已被任意地解析为当前未解决的承诺列表,并且不需要在以后添加任何承诺。

我可以做这样的事情:

const promises = [
    getSomething(),
    getSomethingElse(),
];
const alldone = Promise.all(promises);
await Promise.all([alldone, getAThirdThing()]);

但我想在添加.then()之前在allDone上致电getAThirdThing()

2 个答案:

答案 0 :(得分:2)

Promise.all会自行返回一个Promise,因此您可以连续致电Promise.all

let finished = Promise.all([...]);
finished = Promise.all([finished, someFunctionReturningAnotherPromise()]);
finished = Promise.all([finished, anotherFunctionReturningAPromise()]);
// etc...
// finally:
await finished;

但是,您无法做的是在<{em> await Promise.all返回的承诺之后添加到承诺链

另外,如果你想要访问所有承诺的结果,那么事情会变得有点棘手,因为你最终会得到结果的嵌套数组(你可以使用它)像lodash.flattenDeep之类的东西来规范它们。)

答案 1 :(得分:1)

要向一组承诺添加承诺并等待对它们的承诺全部实现,并且能够为该集添加额外的承诺,至少有两种选择:

  1. 创建一个onFulfilled处理程序,由then调用,检查是否有更多的promise等待添加,如果是,则返回一个承诺,将它们(all)链接到另一个使用相同的promise then处理程序。或多或少类似于递归异步方法,如果它们可用,则添加promise。跟踪已完成的结果并将其与承诺操作相匹配,并避免未被发现的拒绝错误仍需要注意。

  2. 编写一个自定义的Promise静态方法或构造函数,在不使用Promise.all的情况下执行您想要的操作。

  3. 作为2的示例,下面的PromiseGroup构造函数返回带有

    的对象
    • 一个promise`属性,它以promises的顺序中的一系列值结算,并被添加到组中,并且
    • 一种add方法,可以按照演示顺序添加承诺。

    &#13;
    &#13;
    function PromiseGroup() {
        var resolve;
        var reject;
        this.promise = new Promise( (r, j) => { resolve = r, reject = j});
        this.settled = false;
    
        const group = this;
        var numAdded = 0;
        var numSettled = 0;
        const values = [];
        const quickReject = reason => reject(reason);
        const fulfill = ( i, value) => {
            values[i] =  value;
            if( ++numSettled === numAdded) {
                resolve( values);
                group.settled = true;
            }
        };
        this.add = function() {
            if( group.settled) {
                console.trace();
                throw new Error("Can't add promises to a settled group");
            }
            for( var j = 0; j < arguments.length; ++j) {
                let i = numAdded + j;
                Promise.resolve( arguments[j])
                .then( value => fulfill( i, value), quickReject);
            }
            numAdded += j;
        };
    }
    
    //********************************************     and test:
    
    async function test() {
      var group = new PromiseGroup();
      group.add( new Promise(resolve=> setTimeout( resolve=>resolve(1), 500, resolve)),
                 new Promise(resolve=> setTimeout( resolve=>resolve(2), 600, resolve)));
      setTimeout( test2, 100, group);
      var values = await group.promise;
      // some more code
      return values
    }
    
    function test2( group) { // add more after await
      group.add( new Promise(resolve=> setTimeout( resolve=>resolve(3), 700, resolve)),
                 new Promise(resolve=> setTimeout( resolve=>resolve(4), 400, resolve)));
    }
    
    test().then( values=>console.log(JSON.stringify(values)));
    &#13;
    &#13;
    &#13;

    这个答案背后的原因是Promise.allPromise.race是一组最小和最低级别的承诺聚合方法,它们的存在不需要排除新方法的发展。

    使用PromiseGroup或类似的智慧是一个单独的考虑因素。就个人而言,我会审查应用程序的整体异步设计,看看是否可以将可选的promises与promise函数结合起来,如果可能的话,它们会在到达Promise.all或group阶段之前确定它们的需要。