简体   繁体   English

从 Await 调用中捕获错误后,如何在 Express.js 中停止执行?

[英]How do I stop execution in Express.js after catching an error from an Await call?

I find lots of posts that almost answer the question, but nothing quite works for me.我发现很多帖子几乎可以回答这个问题,但没有什么对我有用。

I have an async function:我有一个异步 function:

const doStuff = async (data)=>{
    if(data == "a bug")
        throw(new Error('Error! Bug found'));
    return "not a bug";
}

I call the function on a route handler:我在路由处理程序上调用 function:

app.get('/doStuffRoute', async (req, res, next)=>{
    const result = await doStuff("a bug")
                        .catch((err)=>{return next(err);});

    console.log("This shouldn't execute!");
}

The error gets handled just fine by my custom error middleware, prints out the error, etc. But then I still see This shouldn't execute!我的自定义错误中间件可以很好地处理错误,打印出错误等。但是我仍然看到This shouldn't execute! being printed as well!也被打印出来了!

From all my research and reading, await X.catch(error) should be identical to try{ await X } catch {error} .根据我的所有研究和阅读, await X.catch(error)应该try{ await X } catch {error}相同。 And I really prefer .catch();我真的更喜欢.catch(); if at all possible.如果可能的话。 There are dozens and dozens of tutorials showing this, and even a few stackoverflow posts explicitly stating this to be the case.有几十个教程展示了这一点,甚至一些 stackoverflow 帖子明确说明了这种情况。 However I also occasionally find a post cryptically saying "don't use await with.catch()" with no other explanation or detail, so I don't know what to think.然而,我偶尔也会发现一个帖子神秘地说“不要使用 await with.catch()”,没有其他解释或细节,所以我不知道该怎么想。

The only hint I can find is adding return before your next(err) call should be enough to halt execution, but it doesn't seem to actually work if return next(err);我能找到的唯一提示是在你的next(err)调用之前添加return应该足以停止执行,但如果return next(err);它似乎实际上不起作用is inside a .catch() block.位于.catch()块内。

What is going on?到底是怎么回事? Are my sources lying?我的消息来源在撒谎吗? Am I misunderstanding some basic fundamental concept?我是否误解了一些基本的基本概念? I appreciate any help getting me on track.我很感激任何帮助我走上正轨。

As a bonus question, why do so many people suggest a wrapper function a-la express-async-handler ?作为一个额外的问题,为什么这么多人建议使用包装器 function a-la express-async-handler Why would this have any different behavior than just calling the async function directly and handling it?为什么这与直接调用异步 function 并处理它有任何不同的行为?

A rejected promise does not stop further Javascript execution so that's why the .catch() handler doesn't stop anything.被拒绝的 promise 不会停止进一步的 Javascript 执行,所以这就是.catch()处理程序不会停止任何事情的原因。 In fact, since async functions are asynchronous, your console.log() will even execute before the .catch() handler does.事实上,由于async函数是异步的,你的console.log()甚至会在.catch()处理程序之前执行。 As such, you need to design code flow that respects the promise state.因此,您需要设计符合 promise state 的代码流。

I would suggest this:我建议这样做:

app.get('/doStuffRoute', async (req, res, next) => {
    try {
        const result = await doStuff("a bug");
        console.log("doStuff() resolved");
    } catch(err) {
        console.log("doStuff() rejected");
        next(err);
    }
}

This way, you've clearly delineated the two code paths for a resolved promise and for a rejected promise and you can place code in the appropriate code path.这样,您已经清楚地描绘了已解析 promise 和已拒绝 promise 的两个代码路径,您可以将代码放置在适当的代码路径中。

When you do当你这样做

const result = await doStuff("a bug").catch((err)=>{return next(err);});
console.log(result) // you will see undefined 

because it is trying to evaluate next method when you pass parameter err and store it in result variable, similarly if you do something like this,因为当您传递参数 err 并将其存储在结果变量中时,它会尝试评估下一个方法,类似地,如果您执行类似的操作,

  const add = (err)=>{
    if(err instanceof Error){ return 2}
    return 3
   }
const result = await doStuff("a bug").catch((err)=>{return add(err);});
console.log(result) // you will see 2

Answering your question, when you have a return statement inside a callback function only the callback function's execution ends.回答您的问题,当您在回调 function 中有 return 语句时,只有回调函数的执行结束。 which means the main parent function will continue it's execution.这意味着主父 function 将继续执行。

const result = await doStuff("a bug").catch((err)=>{return err;});
console.log(result) // now result is an Error object
if(result instanceof Error){
 next(result) //if an error handler is defined call that or call default express error handler
 return //stop execution of route callback
} 
console.log("will NOT execute if there is an error")

but I would like to add there are better way of handling errors for async express routes, This article explains it in detail.但我想补充一点,有更好的方法来处理异步快速路由的错误,这篇文章详细解释了它。

https://zellwk.com/blog/async-await-express/ https://zellwk.com/blog/async-await-express/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM