简体   繁体   English

如何推送到Promise.all(Array)

[英]How to push onto Promise.all(Array)

I don't think this is possible with the native promise implementation, but here's the basic idea of what I want: 我认为原生的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;

In reality Promise.all() doesn't care that I pushed something onto the promises array. 实际上, Promise.all()不在乎我将某些内容推送到promises数组中。

Is there a similar pattern which accomplishes the same thing? 是否有完成相同任务的相似模式? Specifically, adding other promises to wait for, as they become known to a list of currently unresolved promises, arbitrarily, and without any requirement that any be added later. 具体来说,随意添加其他的promise,以等待当前未解决的promise列表所知道的等待,并且不需要以后再添加。

I could do something like this instead: 我可以做这样的事情:

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

But I want to call .then() on allDone prior to adding getAThirdThing() . 但是,我想打电话.then()allDone加入之前getAThirdThing()

Promise.all returns a Promise itself, so you can call Promise.all consecutively: Promise.all本身Promise.all返回Promise,因此您可以连续调用Promise.all

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

However, what you can't do is add to the Promise chain after await ing the promise returned by Promise.all . 但是,您不能做的是 await Promise.all返回的promise 之后将其添加到Promise链中。

Also, things get a little tricky if in that scenario if you want to access the results of all the promises, as you'd end up with nested arrays of the results (which you could use something like lodash.flattenDeep to normalize them). 同样,如果在这种情况下,如果您想访问所有 promise的结果,则事情会变得有些棘手,因为最终会得到嵌套的结果数组(可以使用lodash.flattenDeep之类的东西对它们进行规范化)。

To add promises to a set of promises and wait on a promise for them all to be fulfilled, with the ability to add additional promises to the set, there are at least two choices: 要将承诺添加到一组承诺中并等待它们全部兑现,并且能够向该承诺中添加其他承诺,至少有两个选择:

  1. Create an onFulfilled handler, called by then that checks if more promises are waiting to be added, and if so returns a promise for them (all) to be settled chained to another promise using the same then handler. 创建一个onFulfilled处理程序, then调用,该处理程序检查是否有更多的诺言正在等待添加,如果是,则返回一个诺言,供他们(全部)使用相同的then处理程序链接到另一个诺言进行结算。 More or less akin to a recursive asynchronous method that adds promises if they are available. 或多或少类似于递归异步方法,该方法添加了promise(如果可用)。 Keeping track of fulfilled results and matching them with promise operations, and avoiding uncaught rejection errors would still need attention. 跟踪实现的结果并将其与promise操作匹配,并避免未捕获的拒绝错误仍然需要注意。

  2. Write a custom Promise static method or constructor that does what you want instead without using Promise.all . 编写一个自定义的Promise静态方法或构造函数,而不使用Promise.all即可执行Promise.all

As an example of 2., the PromiseGroup constructor below returns an object with 作为2的示例,下面的PromiseGroup构造函数返回一个对象,该对象带有

  • a promise` property that is settled with an array of values in the order promises were added to the group, and 按将promise添加到组中的顺序的一组值结算的promise属性,并且
  • an add method that adds promises to be settled in order of presentation. 一个add方法,该方法添加按演示顺序结算的promise。

 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))); 

The reasoning behind this answer is that Promise.all , and Promise.race are a minimal and low level set of promise aggregation methods and their presence need not preclude the development of new ones. 该答案背后的原因是Promise.allPromise.race是最低限度和低水平的Promise.race聚合方法集,它们的存在不排除需要开发新方法。

The wisdom of using PromiseGroup or similar is a separate consideration. 使用PromiseGroup或类似方法的智慧是一个单独的考虑。 Personally I would review overall asynchronous design of the application to see if optional promises could be combined with promise operations that determine their need, if possible, before ever reaching the Promise.all or group stage. 我个人将审查应用程序的整体异步设计,以查看是否可以在达到Promise.all或组阶段之前将Promise.all与可以确定其需求的Promise.all操作结合使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM