节点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
答案 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(...)
}