在array#map

时间:2017-07-11 07:47:36

标签: javascript node.js express asynchronous

节点8.1.2,我有一个结构,其中一个文件在地图中调用另一个文件的功能。在一个真实的例子中,我会在Promise.all上使用map,但这不是问题。结构如下:

A.js:

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

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

  return res.status(200).json(...)
}

B.js:

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

module.exports = { b }

行。所以在函数b中,我尝试获取一些异步数据(来自数据库)。它失败并抛出一个未被捕获的承诺拒绝。

如何处理它?<​​/ p>

我尝试了多种解决方案:

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(...)
}

但这仍未被捕获。

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(...)
}

仍然未得到处理。我尝试使用Promise.all,我尝试了两个try-catch块(因为我认为map中的一个可能会从next结果返回map而不是实际来自expressStuff功能。仍然没有。

我得到答案的关闭是处理错误,但代码不会等待它被抛出,res.status()next都会起作用,导致竞争条件和{{ 1}}错误。

我想要做的就是让函数cannot set headers after they are sent抛出错误但在b中抓住它,这样我就可以重新抛出自定义expressStuff并将其传递给UnprocessableEntityError 。文件next中的错误似乎没有冒泡到调用它的B

我该怎么做?

编辑:

我能够处理这种拒绝的唯一方法是在map中尝试捕捉它。但是,如果我试图重新抛出错误/返回它 - 没有。误吞了。如果我尝试B.js它,它将被记录。

详情:

感谢有明确的回答,我重构了我的实际代码并使其完美运行。

console.log

1 个答案:

答案 0 :(得分:3)

使用try / catch处理拒绝仅适用async function s 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(...)
}

或(如Wait until all ES6 promises complete, even rejected promises

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(...)
}