Nodejs 如何监听express运行时错误?

Nodejs 如何监听express运行时错误?

使用日志工具winston,在某个测试js文件里面,可以正常监听到运行时错误,并可以将错误信息写入指定文件。如 var winston = require(‘winston’); winston.add(winston.transports.File, { filename: ‘somefile.log’, handleExceptions: true }); var s; s.length

但是放到express里面,就不能监听到路由方法里面的运行时错误了,这是什么原因呢,有没有办法解决?

2 回复

Node.js 如何监听 Express 运行时错误?

在使用 Express 框架开发 Node.js 应用程序时,处理运行时错误是非常重要的。尽管你可以使用日志工具(如 Winston)来记录错误,但在 Express 中直接捕获和处理这些错误需要一些特定的配置。

原因分析

当你在普通的 JavaScript 文件中使用 Winston 并设置 handleExceptionstrue 时,Winston 能够捕获未处理的异常并将其写入日志文件。然而,Express 的中间件机制可能会覆盖或忽略这些未处理的异常,导致它们无法被捕捉。

解决方案

要确保在 Express 应用中能够正确捕获和处理运行时错误,可以通过以下几种方式:

  1. 全局错误处理中间件:Express 提供了一种全局错误处理中间件,专门用于捕获和处理应用中的错误。
  2. 错误事件监听器:你也可以监听 process.on('uncaughtException')process.on('unhandledRejection') 事件来捕获未处理的异常和拒绝的 Promise。

下面是具体的实现代码示例:

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

// 初始化 Express 应用
const app = express();

// 配置 Winston 日志记录器
const logger = winston.createLogger({
    transports: [
        new winston.transports.Console({ level: 'debug' }),
        new winston.transports.File({ filename: 'error.log', level: 'error' })
    ]
});

// 全局错误处理中间件
app.use((err, req, res, next) => {
    logger.error(`${err.status || 500} - ${err.message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
    res.status(err.status || 500).send(err.message);
});

// 示例路由
app.get('/', (req, res) => {
    throw new Error("这是一个故意抛出的错误");
});

// 启动服务器
const port = process.env.PORT || 3000;
app.listen(port, () => {
    console.log(`服务器正在监听端口 ${port}`);
});

// 监听未捕获的异常
process.on('uncaughtException', (err) => {
    logger.error(`未捕获的异常: ${err.message}`);
    process.exit(1); // 强制退出进程
});

// 监听未处理的 Promise 拒绝
process.on('unhandledRejection', (reason, promise) => {
    logger.error(`未处理的 Promise 拒绝: ${reason}`);
});

解释

  • 全局错误处理中间件app.use() 中定义了一个错误处理中间件,它接收四个参数 (err, req, res, next),当有错误发生时会被调用。
  • Winston 配置:创建一个 Winston 日志记录器实例,并配置它将错误记录到控制台和文件中。
  • 进程事件监听:通过监听 uncaughtExceptionunhandledRejection 事件,可以捕获应用程序中未处理的异常和 Promise 拒绝。

通过这种方式,你可以确保在 Express 应用中全面捕获和记录运行时错误。


要在Express应用中监听运行时错误,你可以通过定义全局的错误处理中间件来实现。这些中间件专门用于处理在路由处理函数中抛出的异常或错误。下面是一个简单的例子来展示如何做到这一点:

示例代码

首先确保你的Express应用已经安装并引入了express模块。

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

// 使用日志工具winston进行错误记录
const winston = require('winston');
app.use((req, res, next) => {
    winston.add(winston.transports.File, { filename: 'somefile.log', handleExceptions: true });
    next();
});

// 定义一个简单的路由来演示错误
app.get('/', (req, res, next) => {
    try {
        const s = null;
        console.log(s.length); // 故意制造一个运行时错误
    } catch (error) {
        next(error); // 将错误传递给错误处理中间件
    }
});

// 全局错误处理中间件
app.use((err, req, res, next) => {
    winston.error(`${err.message}`);
    res.status(500).send("Something broke!");
});

// 启动服务器
app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 引入winston并添加文件传输器:在每个请求处理之前,我们设置了一个中间件来初始化winston日志记录器,这样它就可以捕获到所有发生的错误。

  2. 创建错误:在路由处理函数中,我们故意引发了一个错误(试图访问null对象的length属性)。

  3. 错误传递给中间件:通过调用next(error),我们可以确保错误被传递到后续的错误处理中间件。

  4. 全局错误处理中间件:当有错误被传递给这个中间件时,它会记录错误信息,并返回一个HTTP状态码为500的响应。

通过这种方式,你可以在Express应用中监听并处理运行时错误。注意,这个错误处理中间件应该放在所有的路由处理函数之后,因为一旦它被执行,Express就不会再继续执行其他的中间件或路由。

回到顶部