Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/431.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如果没有';快速故障';行为?_Javascript_Asynchronous_Promise_Async Await - Fatal编程技术网

Javascript 如果没有';快速故障';行为?

Javascript 如果没有';快速故障';行为?,javascript,asynchronous,promise,async-await,Javascript,Asynchronous,Promise,Async Await,我正在使用async/await并行触发几个api调用: async function foo(arr) { const results = await Promise.all(arr.map(v => { return doAsyncThing(v) })) return results } 我知道,与循环不同,承诺.all(也就是说,等待结果部分是并行的) 但是: 如果其中一个元素被拒绝,则所有元素都被拒绝,并且 承诺。一切都会很快失败:如果你有四个承诺,都会很

我正在使用
async
/
await
并行触发几个
api
调用:

async function foo(arr) {
  const results = await Promise.all(arr.map(v => {
     return doAsyncThing(v)
  }))
  return results
}
我知道,与
循环不同,
承诺.all
(也就是说,等待结果部分是并行的)

但是:

如果其中一个元素被拒绝,则所有元素都被拒绝,并且 承诺。一切都会很快失败:如果你有四个承诺,都会很快解决 一个超时,一个立即拒绝,然后承诺。所有拒绝 马上

在阅读本文时,如果我
Promise.all
有5个承诺,并且第一个完成的承诺返回一个
reject()
,那么其他4个承诺将被有效取消,它们承诺的
resolve()
值将丢失

还有第三条路吗?执行是有效并行的,但一次失败不会破坏整个过程

ES2020包含,可执行您想要的操作

Promise.allselled([
承诺。决议(“a”),
承诺。拒绝('b')

]).then(console.log)
虽然公认答案中的技术可以解决您的问题,但它是一种反模式。用错误来解决承诺不是一种好的做法,有一种更干净的方法可以做到这一点

在伪代码中,您要做的是:

fn task() {
  result-1 = doAsync();
  result-n = doAsync();

  // handle results together
  return handleResults(result-1, ..., result-n)
}
这只需使用
async
/
wait
即可实现,无需使用
Promise.all
。一个有效的例子:

console.clear();
函数等待(毫秒、数据){
返回新承诺(resolve=>setTimeout(resolve.bind(this,data),ms));
}
/** 
*因为我们调用
*函数,并立即等待每个结果,
*所以这将在1s内完成。
*/
异步函数系列(){
返回{
结果1:等待等待(500,'seriesTask1'),
结果2:等待等待(500,'seriesTask2'),
}
}
/** 
*这里我们先调用函数,
*然后等待结果,所以
*这将在500毫秒内完成。
*/
异步函数并行(){
const task1=wait(500,'parallelstask1');
const task2=wait(500,'parallelTask2');
返回{
结果1:等待任务1,
结果2:等待任务2,
}
}
异步函数taskRunner(fn,标签){
const startTime=performance.now();
log(`Task${label}start…`);
让结果=等待fn();
log(`Task${label}在${Number.parseInt(performance.now()-startTime)}毫秒内完成,带,`,result);
}
void taskRunner(系列,'系列');

void taskRunner(parallel,“parallel”)其他四个不会被取消,但它们的结果不会沿着承诺链(IIUC)传播。如果您希望避免拒绝承诺链的特定失败模式,则可以在子承诺链中处理该失败(使用
catch
),从而避免快速失败。这能满足您的需要吗?
const noop=function(){}
Promise.all(arr.map(v=>doasynchthing(v.catch(noop))
将错误转化为未定义的错误-value@BenAston你的意思是不是用
返回doasynchthing(v)
返回doasynchthing(v).catch(err=>{returnerr})
?ETA:我不确定
catch
正文中应该包含什么内容--是否有一种方法可以将错误对象向上传递,而不包含
reject
?只要我可以单独处理
reject()
ed承诺,并且仍然从
resolve()
d承诺中获取值。回复:
取消
未传播
相比,我不确定我是否理解其中的区别。这两种方法都会导致丢失
resolve()
值,是吗?@Thomas如果
reject()
ed的承诺被拒绝,那么会不会以
undefined
的形式出现在结果
数组中呢?return await是多余的,仅供参考。那么当你已经使用await时,为什么还要使用它呢?您可以删除所有。然后调用就可以了。脚本的输出不包括'bar result'和'bat result',但是:done[undefined,{“error”:“bam”},undefined]是有意的吗?是的,我相信它应该
返回新的承诺
,这样我们就可以得到正确的结果数组:添加到David的注释中,已完成[未定义,{“错误”:“bam”},未定义]返回。如果为bam添加return Wait和then,则结果显示为[Log]done–[“bar结果”、“bam结果”、“bat结果”]。但是,我无法完成结果–[“bar result”,{“error”:“bam”},“bat result”]。有没有办法做到这一点?没有得到应有的重视。这非常清楚地表明了正在发生的事情。“反模式:用错误解决承诺不是好的实践”-你从哪里得到的?不,恰恰相反,这可能会导致未经处理的拒绝。更糟糕的是:这甚至不能解决老年退休金问题。如果
task1
task2
完成之前拒绝,您仍然很快就失败了。您从哪里得到的在
then
中处理错误是反模式的,因为Promises有一种专门的方法来处理
catch
分支中的错误,因此开发人员期望
then
中的值和
catch
中的错误。混用这一点会让其他不知道您的自定义实现细节的人感到困惑。您的并行函数是一个反模式-如果您阅读了我的答案,您可以在底部找到如何处理它:“这样,您可以使用try/catch来处理错误,并在并行函数中返回部分结果。”这也是你第二条评论的答案:更糟糕的是,这甚至不能解决老年退休金问题。