[英]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: 要将承诺添加到一组承诺中并等待它们全部兑现,并且能够向该承诺中添加其他承诺,至少有两个选择:
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操作匹配,并避免未捕获的拒绝错误仍然需要注意。
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
构造函数返回一个对象,该对象带有
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.all
和Promise.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.