反模式聚合错误并传递给promise解决js?

时间:2016-12-21 07:28:26

标签: javascript es6-promise

我正在循环中处理一个列表,该循环运行async返回一个promise而我不想退出处理异常,所以我聚合它们并将它们传递给外部finally块中的resolve回调。 我想知道这是否是反模式,如果是,请提供一个如何正确执行的指针。 感谢。

实施例

async doSomething(list) {
let errorCount = 0
let errors = []
return new Promise(async (resolve, reject) => {
  try {
    list.forEach(async (item) => {
      try {
        actionThatThrows(item)
      } catch (e) {
        errorCount++
        errors[errorCount] = e
      }
    })
  } catch (e) {
    errorCount++
    errors[errorCount] = e
  } finally {
    if (errorCount > 0) {
      resolve(errors)
    } else {
      resolve()
    }
  }
})

}

3 个答案:

答案 0 :(得分:8)

是的,此代码使用了几个反模式:

  

我不想退出处理异常但聚合它们

您可能需要查看Wait until all ES6 promises complete, even rejected promises

但是假设你想要连续迭代,你可以在没有这些的情况下做到这一点:

async function doSomething(list) {
    const errors = [];
    for (let item of list) {
        try {
            await actionThatThrows(item);
        } catch (e) {
            errors.push(e);
        }
    }
    if (errors.length)
        return errors;
    else
        return …;
}

答案 1 :(得分:3)

错误是异步计算的结果,因此全局看起来是合法的。

假设actionThatThrows返回一个承诺(在你的问题和代码中不清楚),它看起来像是这样写的:

function doSomething(list) {
    let errors = []
    return Promise.all(list.map(
        item => actionThatThrows(item).catch(e => {
            errors.push(e);
        })
    )).then(()=>{
        return errors.length ? errors : undefined;
    });
}

答案 2 :(得分:0)

1)async doSomething没有调用await,所以删除异步 2)list.forEach中的异步不是调用await,所以删除异步 3)第一次捕获将捕获所有。第二次捕获将永远不会被击中,因此删除第二次捕获并最终

代码可以简化为:

doSomething(list) {
    let errorCount = 0,
        errors = [];
    for (let item of list) {
        try {
            actionThatThrows(item); //I suppose this is not returning a promise
        } catch (e) {
            errorCount += 1;
            errors[errorCount] = e;
        }
    }
    if (errorCount > 0) {
        return errors; //return Promise.reject(errors);
    } else {
        //return Promise.resolve();
    }
}