我不认为这可以通过本机承诺实现,但这是我想要的基本概念:
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()
。
答案 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)
要向一组承诺添加承诺并等待对它们的承诺全部实现,并且能够为该集添加额外的承诺,至少有两种选择:
创建一个onFulfilled处理程序,由then
调用,检查是否有更多的promise等待添加,如果是,则返回一个承诺,将它们(all)链接到另一个使用相同的promise then
处理程序。或多或少类似于递归异步方法,如果它们可用,则添加promise。跟踪已完成的结果并将其与承诺操作相匹配,并避免未被发现的拒绝错误仍需要注意。
编写一个自定义的Promise静态方法或构造函数,在不使用Promise.all
的情况下执行您想要的操作。
作为2的示例,下面的PromiseGroup
构造函数返回带有
add
方法,可以按照演示顺序添加承诺。
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;
这个答案背后的原因是Promise.all
和Promise.race
是一组最小和最低级别的承诺聚合方法,它们的存在不需要排除新方法的发展。
使用PromiseGroup
或类似的智慧是一个单独的考虑因素。就个人而言,我会审查应用程序的整体异步设计,看看是否可以将可选的promises与promise函数结合起来,如果可能的话,它们会在到达Promise.all
或group阶段之前确定它们的需要。