在Array#map中处理async / await中的错误(拒绝) [英] Handling Errors (Rejections) in async/await inside Array#map
问题描述
节点8.1.2,我有一个结构,其中一个文件在地图中调用另一个文件的功能。在一个真实的例子中,我会在地图
上使用 Promise.all
,但这不是问题。结构如下:
A.js:
const {b} = require('./ B')
函数expressStuff(req,res,next){
things.map( thing => {
返回b(东西)
}))
返回res.status(200).json(...)
}
B.js:
// Thing - >无极<对象>
函数b(东西){
返回ThingModel.update(...)//这会返回一个Promise但是FAILS并抛出一个错误的
}
模块。 exports = {b}
好的。所以在函数 b
中我尝试获取一些异步数据(来自数据库)。它失败并抛出一个未被捕获的承诺拒绝。
如何处理它?</ p>
我试过多个解决方案:
A1.js:
const {b} = require('./ B')
函数expressStuff(req,res,next){
things.map(thing => {
try {
return b(thing)
} catch(err){
return next(err)
}
}))
返回res.status(200).json(...)
}
但这仍未被捕获。
A2.js
:
const {b} = require('./ B')
函数expressStuff(req,res,next){
try {
things.map(thing => {
return b(thing)
}))
} catch(err){
return next(err)
}
返回res.status(200).json(...)
}
仍未处理。我尝试使用 Promise.all
,我尝试了双重try-catch块(因为我认为 map
中的那个可能是返回下一步
从地图
结果而不是实际来自 expressStuff
function。仍然没有。
我得到答案的关闭是处理错误但是代码不会等待它被抛出而且 res.status()
和 next
会导致竞争条件,在发送后无法设置标头
错误。
我想做的就是用函数 b
抛出一个错误,但在 expressStuff
中捕获它,所以我可以重新抛出自定义 UnprocessableEntityError
并将其传递给
。似乎文件 B
中的错误没有冒泡到地图
所在的地方被叫。
我该怎么做?
编辑:
我可以做这个rej的唯一方法处理的是在 B.js
中尝试捕获它。但是,如果我试图重新抛出错误/返回它 - 没有。误吞了。如果我尝试 console.log
它 - 它将被记录。
DETAILS:
由于标记的答案,我重构了我的实际代码并使其完美运行。
function expressStuff(res,req,next){
try {
await Promise.all(things.map(async thing => {
if(ifSomething()){
await b(thing)
}
}))
} catch(错误){
返回下一个(新的MyCustomError('我的自定义错误消息'))
}
返回res.status(200).json(...)
}
使用处理拒绝尝试
/ catch
仅适用 async function
当你等待
承诺时 - 你还没有尝试过。
你可以做任何一个
异步函数expressStuff(req,res,next){
var结果;
try {
results = await Promise.all(things.map(b)); //当任何承诺拒绝时抛出
} catch(错误){
返回下一个(错误)//处理错误
}
返回res.status(200).json (...)
}
function expressStuff(req,res,next){
const resultPromises = things.map(async(thing)=> {
尝试{
返回await b(thing); //当这个特殊事物的承诺拒绝
} catch时抛出(错误){
返回defaultValue; //处理错误 - 不要调用`next` here
}
});
...
返回res.status(200).json(...)
}
Node 8.1.2, I have a structure where one file is calling another file's function in a map. In a real example I would use Promise.all
on the map
but that's not the question here. Here is the structure:
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 }
OK. So in function b
I try to get some async data (from a database). It fails and throws an Uncaught Promise Rejection.
How to make deal with it?
I tried multiple solutions:
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(...)
}
But that is still uncaught.
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(...)
}
Still unhandled. I tried using Promise.all
, I tried double try-catch blocks (since I thought the one inside map
might be returning next
from the to the map
result and not actually from expressStuff
function. Still nothing.
The closes I got to the answer was handling the error but then code wouldn't wait for it to be thrown and both res.status()
and next
would work resulting in race conditions and cannot set headers after they are sent
errors.
All I want to do is for the function b
to throw an error but catch it in the expressStuff
so I can rethrow custom UnprocessableEntityError
and pass it to next
. It seems like error from file B
is not bubbling up to the map
where it is called.
How do I do it?
EDIT:
The only way I can make this rejection handled is try-catching it in the B.js
. But if I try to rethrow an error/return it - nothing. Error is swallowed. If I try to console.log
it - it will be logged though.
DETAILS:
Thanks to marked answer I refactored my actual code and made it to work perfectly.
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(...)
}
Handling rejections with try
/catch
works only in async function
s when you await
the promise - which you haven't attempted yet.
You could do either
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(...)
}
or (like 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(...)
}
这篇关于在Array#map中处理async / await中的错误(拒绝)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!