Javascript 正在等待多个并发等待操作

Javascript 正在等待多个并发等待操作,javascript,promise,async-await,ecmascript-2017,Javascript,Promise,Async Await,Ecmascript 2017,如何更改以下代码,以便触发这两个异步操作并使其有机会并发运行 const value1 = await getValue1Async(); const value2 = await getValue2Async(); // use both values 我需要这样做吗 const p1 = getValue1Async(); const p2 = getValue2Async(); const value1 = await p1; const value2 = await p2; // us

如何更改以下代码,以便触发这两个异步操作并使其有机会并发运行

const value1 = await getValue1Async();
const value2 = await getValue2Async();
// use both values
我需要这样做吗

const p1 = getValue1Async();
const p2 = getValue2Async();
const value1 = await p1;
const value2 = await p2;
// use both values

我认为这应该奏效:

 const [value1, value2] = await Promise.all([getValue1Async(),getValue2Async()]);
下面是一个更详细的示例,以帮助理解:

const promise1=async()=>{
返回3;
}
常量promise2=async()=>{
返回42;
}
常量promise3=async()=>{
返回500;
//模仿错误
//抛出“出了问题……”;
}
常量f1=async()=>{
试一试{
//返回一个值数组
const results=等待承诺。全部([promise1(),promise2(),promise3());
控制台日志(结果);
console.log(结果[0]);
console.log(结果[1]);
console.log(结果[2]);
//通过“数组分解”将值分配给各个变量
const[value1,value2,value3]=等待承诺。全部([promise1(),promise2(),promise3());
console.log(value1);
console.log(value2);
console.log(value3);
}捕捉(错误){
log(“出现错误:+err”);
}
}

f1()我认为这应该有效:

 const [value1, value2] = await Promise.all([getValue1Async(),getValue2Async()]);
下面是一个更详细的示例,以帮助理解:

const promise1=async()=>{
返回3;
}
常量promise2=async()=>{
返回42;
}
常量promise3=async()=>{
返回500;
//模仿错误
//抛出“出了问题……”;
}
常量f1=async()=>{
试一试{
//返回一个值数组
const results=等待承诺。全部([promise1(),promise2(),promise3());
控制台日志(结果);
console.log(结果[0]);
console.log(结果[1]);
console.log(结果[2]);
//通过“数组分解”将值分配给各个变量
const[value1,value2,value3]=等待承诺。全部([promise1(),promise2(),promise3());
console.log(value1);
console.log(value2);
console.log(value3);
}捕捉(错误){
log(“出现错误:+err”);
}
}
f1()TL;博士
不要在你得到承诺的问题上使用这种模式,然后分别等待它们;相反,使用
Promise.all
(至少现在):

虽然您的解决方案确实并行运行这两个操作,但如果两个承诺都拒绝,则无法正确处理拒绝

细节: 您的解决方案并行运行它们,但总是先等待第一个完成,然后再等待第二个完成。如果您只想启动它们,并行运行它们,并获得这两个结果,那么这很好。(不,不是,请继续阅读…)请注意,如果第一个需要(比如)五秒钟才能完成,而第二个在一秒钟内失败,那么代码将等待整整五秒钟,然后失败

遗憾的是,目前没有执行并行等待的
wait
语法,因此您有您列出的尴尬,或者
Promise.all
。(尽管有,也许有一天。)

承诺。所有
版本为:

const [value1, value2] = await Promise.all([getValue1Async(), getValue2Async()]);
…更简洁,并且如果第二个操作快速失败,也不会等待第一个操作完成(例如,在我上面的5秒/1秒示例中,上面的操作将在1秒内拒绝,而不是等待5秒)。还要注意的是,对于您的原始代码,如果第二个承诺在第一个承诺解决之前被拒绝,您很可能会在控制台中得到一个“未处理的拒绝”错误(您目前使用的是Chrome v61;更新:较新版本),尽管该错误可能是虚假的(因为您最终会处理拒绝,因为此代码显然位于
异步
函数中,因此该函数将钩住拒绝并使其承诺被拒绝)(再次更新:)。但是如果两个承诺都拒绝,您将得到一个真正的未经处理的拒绝错误,因为控制流从未达到
const value2=wait p2;
,因此p2拒绝从未得到处理

未经处理的拒绝是件坏事™ (如此之多以至于很快,Node.js将中止处理真正未经处理的拒绝,就像未经处理的异常一样——因为它们就是这样),所以最好避免您的问题中的“获得承诺然后
wait
it”模式

以下是故障情况下定时差异的示例(使用500毫秒和100毫秒,而不是5秒和1秒),也可能是虚假的未处理拒绝错误(打开real浏览器控制台查看):

const getValue1Async=()=>{
返回新承诺(解决=>{
设置超时(解析,500,“值1”);
});
};
常量getValue2Async=()=>{
返回新承诺((解决、拒绝)=>{
设置超时(拒绝,100,“错误”);
});
};
//这会在失败之前等待整整500毫秒,因为它会等待
//在p1上,然后在p2上
(异步()=>{
试一试{
控制台。时间(“分开”);
常量p1=getValue1Async();
常量p2=getValue2Async();
常数值1=等待p1;
常数值2=等待p2;
}捕获(e){
控制台错误(e);
}
控制台。时间结束(“单独”);
})();
//这在100毫秒后失败,因为它不等待p1
//要首先完成,它会在p2拒绝时立即拒绝
setTimeout(异步()=>{
试一试{
时间(“承诺一切”);
const[value1,value2]=wait Promise.all([getValue1Async(),getValue2Async()]);
}捕获(e){
console.timeEnd(“Promise.all”,e);
}
},1000);
打开real browser控制台查看未处理的拒绝错误。
TL;DR 不要在你得到承诺的问题上使用这种模式,然后分别等待;相反,使用
Promise.all
(至少现在):

虽然您的解决方案确实并行运行这两个操作,但如果两个承诺都拒绝,则无法正确处理拒绝

细节: 您的解决方案并行运行它们,但总是先等待第一个完成,然后再等待第二个。如果您只想启动它们,请并行运行它们,并获得这两个结果,这很好