在 Array#map 中处理 async/await 中的错误(拒绝)

Tom*_*ski 6 javascript asynchronous node.js express

节点 8.1.2,我有一个结构,其中一个文件在映射中调用另一个文件的函数。在一个真实的例子中,我会使用Promise.allmap但这不是这里的问题。这是结构:

A.js:

const { b } = require('./B')

function expressStuff (req, res, next) {
  things.map(thing => {
    return b(thing)
  }))

  return res.status(200).json(...)
}
Run Code Online (Sandbox Code Playgroud)

B.js:

// Thing -> Promise<Object>
function b (thing) {
  return ThingModel.update(...) // this returns a Promise but FAILS and throws an errror
}

module.exports = { b }
Run Code Online (Sandbox Code Playgroud)

好的。所以在函数中,b我尝试获取一些异步数据(从数据库中)。它失败并抛出 Uncaught Promise Rejection。

如何处理?

我尝试了多种解决方案:

A1.js:

const { b } = require('./B')

function expressStuff (req, res, next) {
  things.map(thing => {
    try {
      return b(thing)
    } catch (err) {
      return next(err)
    }
  }))

  return res.status(200).json(...)
}
Run Code Online (Sandbox Code Playgroud)

但这仍然没有被抓住。

A2.js

const { b } = require('./B')

function expressStuff (req, res, next) {

  try {
    things.map(thing => {
      return b(thing)
    }))
  } catch (err) {
    return next(err)
  }

  return res.status(200).json(...)
}
Run Code Online (Sandbox Code Playgroud)

还是没处理好。我尝试使用Promise.all,我尝试了双重 try-catch 块(因为我认为里面的一个map可能是nextmap结果返回到结果而不是实际上从expressStuff函数返回。仍然没有。

我得到的答案被关闭处理错误,但随后的代码将不会等待它抛出两者res.status()next会工作导致竞争条件和cannot set headers after they are sent错误。

我想要做的就是让函数b抛出一个错误,但将它捕获到 中,expressStuff这样我就可以重新抛出自定义UnprocessableEntityError并将其传递给next. 文件中的错误似乎B没有冒泡到map调用它的地方。

我该怎么做?

编辑:

我可以处理这种拒绝的唯一方法是尝试在B.js. 但是如果我尝试重新抛出错误/返回它 - 什么都没有。错误被吞下。如果我尝试这样console.log做 - 它会被记录下来。

细节:

感谢标记的答案,我重构了我的实际代码并使其完美运行。

function expressStuff (res, req, next) {
  try {
    await Promise.all(things.map(async thing => {
      if (ifSomething()) {
        await b(thing)
      }
    }))
  } catch (err) {
    return next(new MyCustomError('My Custom Error Message'))
  }

  return res.status(200).json(...)
}
Run Code Online (Sandbox Code Playgroud)

Ber*_*rgi 7

当您承诺时,使用try/处理拒绝catch仅在async functions 中有效await- 您还没有尝试过。

你可以这样做

async function expressStuff (req, res, next) {
  var results;
  try {
    results = await Promise.all(things.map(b)); // throws when any of the promises reject
  } catch (err) {
    return next(err) // handle error
  }
  return res.status(200).json(...)
}
Run Code Online (Sandbox Code Playgroud)

或者(比如等到所有 ES6 承诺完成,甚至拒绝承诺

function expressStuff (req, res, next) {
  const resultPromises = things.map(async (thing) => {
    try {
      return await b(thing); // throws when the promise for this particular thing rejects
    } catch (err) {
      return defaultValue; // handle error - don't call `next` here
    }
  });
  …
  return res.status(200).json(...)
}
Run Code Online (Sandbox Code Playgroud)