You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Morgan中间件日志晚于自定义中间件输出?Express技术问询

Morgan日志中间件输出顺序问题

我在使用Express框架与Morgan日志中间件时遇到了输出顺序问题:按中间件声明顺序,Morgan日志应该先输出,但实际自定义中间件的“hello”先打印,Morgan需要等待整个请求完成才输出。这是否与Morgan的内部机制有关?我已尝试调整中间件顺序、在app.use中使用异步函数。

可复现问题的Node.js代码:

const express = require('express')
const morgan = require('morgan')

const app = express()

app.use(express.json()) //middleware

const customFormat = (tokens, req, res) => {
    let rarr = [
        tokens.method(req, res),
        tokens.url(req, res),
        tokens.status(req, res),
        tokens.res(req, res, 'content-length'), '-',
        tokens['response-time'](req, res), 'ms'
    ]
    return rarr.join(' ')
  } 

app.use(morgan(customFormat))

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

    console.log("hello");
    next();
});

let data = [
    { 
      "id": 1,
      "name": "alpha"
    },
    { 
      "id": 2,
      "name": "beta", 
    },
    { 
      "id": 3,
      "name": "gamma"
    }
]

app.get("/api/persons", (request, response) => {
    response.send(data)
})

这确实是Morgan的内部机制导致的。Morgan默认会等待整个请求-响应周期完成后才输出日志,因为它需要获取响应状态码、响应时长、响应内容长度这些只有请求处理完毕、响应发送给客户端后才能拿到的信息。

你的自定义中间件是同步执行的,调用next()之前就直接打印了“hello”;而Morgan在执行时,会先注册监听响应的finish或close事件,等响应完全结束后才会执行日志格式化和输出操作——所以不管你把Morgan放在哪个中间件前面,它的日志输出都会晚于那些同步执行的中间件里的console.log。

如果想要让Morgan在请求到达时就输出部分日志(比如仅打印请求方法和URL),可以启用Morgan的immediate选项:

// 启用immediate选项,请求到达时立即输出日志
app.use(morgan(customFormat, { immediate: true }))

注意:启用immediate后,status、response-time这类依赖响应的token会返回空值,你需要调整自定义格式,只保留请求阶段能获取到的字段。


内容的提问来源于stack exchange,提问作者sjdevelop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 00:22:06