当前位置: 首页 > 面试题库 >

处理Express异步中间件中的错误

公冶渝
2023-03-14
问题内容

我有一个asyncExpress中间件,因为我想在其中使用中间件await来清理我的代码。

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

app.use(async(req, res, next) => {
    await authenticate(req);
    next();
});

app.get('/route', async(req, res) => {
    const result = await request('http://example.com');
    res.end(result);
});

app.use((err, req, res, next) => {

    console.error(err);

    res
        .status(500)
        .end('error');
})

app.listen(8080);

问题在于,当它拒绝时,它不会进入我的错误中间件,但是如果我删除了async关键字,并且throw在中间件中,它将删除。

app.get('/route', (req, res, next) => {
    throw new Error('Error');
    res.end(result);
});

所以我得到的UnhandledPromiseRejectionWarning不是输入我的错误处理中间件,而是如何让错误冒泡并表达处理它?


问题答案:

问题是当它拒绝时,它不会进入我的错误中间件,但是如果我删除了async关键字并扔进了中间件中,它就会去。

express 目前不支持诺言,将来的版本可能会支持 express@5.x.x

因此,当您传递中间件函数时,express将在一个try/catch块内调用它。

Layer.prototype.handle_request = function handle(req, res, next) {
  var fn = this.handle;

  if (fn.length > 3) {
    // not a standard request handler
    return next();
  }

  try {
    fn(req, res, next);
  } catch (err) {
    next(err);
  }
};

问题在于,该函数try/catch不会捕获函数Promise外部的拒绝,async并且由于express没有在中间件返回的.catch函数中添加处理程序Promise,因此您会得到一个UnhandledPromiseRejectionWarning

最简单的方法是try/catch在中间件中添加,然后调用next(err)

app.get('/route', async(req, res, next) => {
    try {
        const result = await request('http://example.com');
        res.end(result);
    } catch(err) {
        next(err);
    }
});

但是,如果您有很多async中间件,则可能有些重复。

由于我喜欢中间件尽可能干净,并且通常让错误冒出来,所以我在async中间件周围使用包装器,next(err)如果承诺被拒绝,它将调用,到达明确的错误处理程序并避免UnhandledPromiseRejectionWarning

const asyncHandler = fn => (req, res, next) => {
    return Promise
        .resolve(fn(req, res, next))
        .catch(next);
};

module.exports = asyncHandler;

现在您可以这样称呼它:

app.use(asyncHandler(async(req, res, next) => {
    await authenticate(req);
    next();
}));

app.get('/async', asyncHandler(async(req, res) => {
    const result = await request('http://example.com');
    res.end(result);
}));

// Any rejection will go to the error handler

还有一些可以使用的软件包

  • 异步中间件
  • 表达异步处理程序


 类似资料:
  • 我正在使用Express.js并尝试创建一个catchall异步错误处理程序。假设我有三条路都可能出错, 在这三条路由中,所有getXX函数都可能抛出错误。 我希望所有路由都只有一个异步处理程序。类似这样的东西 所以我不必尝试/捕捉每一个可能抛出错误的地方。对此有什么解决办法吗? 提前道谢!

  • 问题内容: 我对Node.js并不陌生,尽管我通常对JavaScript非常熟悉。我的问题是关于如何处理node.js中的错误的“最佳实践”。 通常,在对Web服务器,FastCGI服务器或各种语言的网页进行编程时,我在多线程环境中使用带有阻止处理程序的Exceptions。当有请求进入时,我通常会执行以下操作: 这样,我始终可以处理内部错误并向用户发送有效响应。 我知道使用node.js可以执行

  • 编写JavaScript代码时,我们要时刻牢记,JavaScript引擎是一个事件驱动的执行引擎,代码总是以单线程执行,而回调函数的执行需要等到下一个满足条件的事件出现后,才会被执行。 例如,setTimeout()函数可以传入回调函数,并在指定若干毫秒后执行: function printTime() { console.log('It is time!'); } setTimeout

  • 问题内容: 我具有以下Spring Integration配置,该配置允许我从MVC Controller调用网关方法并让控制器返回,而集成流将在不阻塞控制器的单独线程中继续进行。 但是,我无法弄清楚如何使我的错误处理程序为该异步流工作。我的网关定义了错误通道,但是由于某种原因我的异常没有到达。相反,我看到被调用了。 网关: 为了查看我的错误处理程序正在处理的异步集成流程中发生的异常,我该怎么办?

  • 我有一个这样的集成流程:

  • 在Spring integration中,我必须处理动态通道创建,但当我调试应用程序时,我看到不同通道之间的“阻塞”问题。 我知道是一个公共通道,在父上下文中共享,但如何为每个子上下文开发一个完整的独立场景?。公共网关是问题所在吗? 我在Spring integration flow async中看到了post错误处理,但对于每个子级,我都有一个完整的分离环境,我希望利用这些动态分离的优势。这可能