arr.forEach()语句的回调中的promise拒绝是否会停止迭代?

时间:2017-05-22 22:17:33

标签: javascript promise bluebird

我有以下函数返回Promise:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all([promise1, promise2]).then(function(results) {
        results.forEach(function(result) {
            return promiseReturningFn();  // Returns a Promise
        });
    }).catch(function(err) {
        console.log(err);
    });
}

关于这段代码我有两个问题:

  1. 在任何forEach()次迭代promiseReturningFn()拒绝的情况下,拒绝是否会被catch()声明捕获?
  2. 如果第一次迭代的promiseReturningFn()拒绝,迭代是否会停止,这意味着不会为结果数组中的第二个元素调用回调?如果这是真的,那么在失败后控制流是否会传递给catch()语句?

1 个答案:

答案 0 :(得分:3)

关于你的两个问题:

  
      
  1. 在任何forEach()迭代的promiseReturningFn()拒绝的情况下,catch()语句是否会捕获拒绝?
  2.   

不,因为你没有在return回调中then承诺,而是在forEach回调中,而后者没有效果 - 这样的返回值会丢失遗忘。

  
      
  1. 如果第一次迭代的promiseReturningFn()拒绝,迭代是否会停止,这意味着不会为结果数组中的第二个元素调用回调?如果这是真的,那么在失败后是否会将控制流传递给catch()语句?
  2.   

不,迭代不会停止。您甚至不会同步知道拒绝,因为此信息只能异步使用(忽略bluebird允许同步检查的时刻。)

以下可能是您应该如何对其进行编码的,假设您在另一个尚未解决的情况下允许promiseReturningFn已经在已解决的承诺上执行:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all(
        [promise1, promise2].map(p => p.then(promiseReturningFn))
    }).catch(function(err) {
        console.log(err);
    });
}

或者,如果在开始为它们执行promiseReturningFn之前确实需要所有解析的数组,那么请执行以下操作:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all([promise1, promise2]).then(results => {
        return Promise.all(results.map(promiseReturningFn));
    }).catch(function(err) {
        console.log(err);
    });
}

在任何一种情况下,现在都会回答你的两个问题:

  • 是的,如果内部承诺拒绝,则会执行catch回调。

  • 不,迭代不会停止,因为promise的结果只是异步知道,所以到那时循环(map)已经完全执行了。

要对第二个问题回答“是”并在前一个返回的承诺拒绝时停止对promiseReturningFn的调用,您必须序列化它们,等待一个承诺在调用promiseReturningFn之前完成再次:

function someFn() {
    // Making use of Bluebird's Promise.all()
    return Promise.all([promise1, promise2]).then(results => {
        return (function loop(i, p) {
            return i >= results.length ? p
                : p.then(_ => loop(i+1, promiseReturningFn(result[i])));
        })(0, Promise.resolve());
    }).catch(function(err) {
        console.log(err);
    });
}