web基础·express错误处理中间件不能捕获异步异常?

在学习的时候,视频里只是说了下【错误处理中间件只能捕获同步异常,不能捕获异步异常】,然后就开始讲怎样来捕获异步异常。但是没有举一个没有成功捕获异步异常的例子来甩在我的脸上,所以就陷入了怀疑的状态,然后开始了自己下面的测试。(可能是有点钻牛角尖吧)

首先呢,先寻摸个异步处理,第一想到的就是定时器

setInterval和setTimeout

前者是每隔多久调用一次;后者是隔多久后调用一次就不再调用。

先来个同步异常,顺便测下定时器程序写对了么 

const express = require('express');
const app = express();

app.get('/demo', (req, res, next) => {
    //当访问/demo时,3秒后执行箭头函数,来测试下这个定时器是正常的
    setTimeout(() => {
        console.log('来了来了');
    }, 3000);
    
    //自己new了个错误,然后通过throw抛出异常,这个异常的抛出是随着对/demo的访问而触发的
    //也就是说是同步的,即刻触发
    throw new Error('同步异常');
})

//错误处理中间件。没有指定匹配路径就默认是/也就是根目录
//所有的路径访问都会经过根目录,所以也可以认为匹配所有请求
app.use((err, req, res, next) => {
    //这里使用错误对象err的message属性来拿到异常/错误信息
    res.status(500).send('use捕获到了异常' + err.message);
})

app.listen(3000, () => {
    console.log('服务器已启动!');
})

powershell中使用nodemon来执行本脚本文件,结果如下:

地址栏访问/demo,页面先呈现出:捕获到同步异常 ;3秒后powershell中出现:来了来了。结果说明:同步异常可以被错误处理中间件正常捕获,定时器也可以正常执行。


下面来使用setTimeout来制造【异步异常】,看看错误中间件能否捕获到错误信息。

const express = require('express');
const app = express();

app.get('/demo', (req, res) => {

    setTimeout(() => {
        console.log('来了来了');

        //当访问/demo时,3秒后抛出异常
        throw new Error('由定时器抛出的异步异常');
    }, 3000);
})

app.use((err, req, res, next) => {
    res.status(500).send('use捕获到了异常:' + err.message);
})

app.listen(3000, () => {
    console.log('服务器已启动!');
})

nodemon执行脚本,结果如下:

发现页面的红框区域里并没有显示出错误信息,而是直接在控制台中报错了,同时页面呈现出访问的网页出错了。说明错误处理中间件并没有捕获到定时器中抛出的异常。

这不就是说明【错误处理中间件不能够捕获异步异常/错误信息吗】

因为错误处理中间件(这里的use)的第一个请求路径参数省略,也就是/,根目录;每个请求都会先走根目录,意味着use是对所有的请求做异常捕获,但是是在有请求时才触发,像上面的请求时没有错误,请求之后3秒出现了错误,但是没有捕获到。这时的use可以视为已经退下了,所以出现了异常也不能捕获。


 解决上面这个问题就是要当出现异常时,重新唤醒错误处理中间件。借助next()来对错误处理中间件进行“唤醒”,告诉它有错误了,把错误以next(error)的方式进行传递,让其对此error进行捕获。

const express = require('express');
const app = express();

//对express对象app的get方法添加next参数,用于错误信息的传递
app.get('/demo', (req, res, next) => {

    setTimeout(() => {
        console.log('来了来了');
        //声明一个变量err来存放异常错误
        let err = new Error('由定时器抛出的异步异常');
        //使用next对异常错误进行传递,‘唤醒’错误处理中间件
        next(err);
    }, 3000);
})

app.use((err, req, res, next) => {
    res.status(500).send('use捕获到了异常:' + err.message);
})

app.listen(3000, () => {
    console.log('服务器已启动!');
})

 执行脚本,地址栏访问http://localhost:3000/demo,结果如下:

访问/demo,3秒后控制台输出“来了来了”,然后页面正常输出捕获到的错误信息。也就是说next(error)可以触发错误处理中间件来对异步产生的错误信息进行获取。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用异步函数是不会逃脱 express 中 app.use 函数的捕获错误机制的。 在 express 中,app.use 函数用于添加中间件函数,这些函数会在请求和响应的生命周期中被调用。如果在这些函数中抛出了错误,那么 express捕获这个错误并将其传递给错误处理中间件。 因此,无论是同步函数还是异步函数,都不会逃脱 express 中 app.use 函数的捕获错误机制。如果你在 app.use 函数中使用了异步函数,那么只需要在函数内部使用 try-catch 语句或者在函数最后使用 await 来捕获并处理异步操作中可能出现的错误即可。 ### 回答2: 在Express中,通过app.use函数注册的中间件会自动捕获发生在其内部的同步错误,并通过next函数将错误传递给错误处理中间件进行处理。这种错误捕获机制可以有效地处理同步错误。然而,对于异步函数,Express错误处理机制是无法自动捕获并处理的。 使用异步函数时,如果在异步函数内部发生错误,Express错误处理机制将无法捕获到这些错误,也无法进行相应的处理。这是因为异步函数的执行是非阻塞的,它们会立即返回一个Promise对象,并在后台执行。在这种情况下,错误发生在异步函数内部,而Express错误处理机制在异步函数返回Promise对象后已经无法获取到这些错误。 为了解决这个问题,我们可以使用try/catch语句来捕获异步函数内部的错误,并手动调用next函数传递错误。这样,错误将被传递到下一个错误处理中间件进行处理。 示例代码如下: app.use(async (req, res, next) => { try { // 异步操作 await someAsyncFunction(); next(); } catch (err) { next(err); } }); 上述代码中,我们使用了async/await语法来处理异步函数,然后在try块中执行异步操作,如果发生错误,则通过next函数将错误传递给下一个错误处理中间件进行处理。 综上所述,使用异步函数时,需要手动处理其中发生的错误,通过try/catch语句捕获错误并调用next函数传递错误,以便Express能够正确地处理它们。 ### 回答3: 使用异步函数不会逃脱express中`app.use`函数的捕获错误的机制。 在Express中,通过定义中间件函数来处理HTTP请求,这些中间件函数可以是同步的,也可以是异步的。无论是同步还是异步中间件函数,Express都会在调用它们时使用try-catch块来捕获可能出现的错误。 在异步函数中,当出现错误时,如果没有使用try-catch语句来显式地捕获错误,这些错误将会被自动转发到错误处理中间件中。错误处理中间件是一个专门用来处理错误的中间件函数,可以用`app.use`或`app.use(errorHandler)`方式来定义。因此,无论是同步的还是异步的函数,只要在处理请求的过程中出现错误,Express都会通过错误处理中间件捕获和处理这些错误。 例如,下面是一个使用异步函数的Express中间件的示例: ``` app.use(async (req, res, next) => { try { // 异步操作 await someAsyncFunction(); // 继续处理请求 next(); } catch (err) { // 错误处理 next(err); } }); ``` 在上述示例中,`someAsyncFunction`是一个异步函数,当它抛出一个错误时,try-catch块会捕获这个错误并通过`next(err)`将其传递给错误处理中间件进行处理。 总之,无论使用同步还是异步函数,Express都会捕获这些函数可能抛出的错误,并通过错误处理中间件来处理这些错误,使得我们能够更好地处理和管理错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值