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

Express中间件失效及浏览器无响应问题求助(疑因文件结构)

Express拆分路由后中间件失效及无响应问题解决

问题背景

我正在学习Express中间件开发,实现了一个记录访问URL到控制台的logger中间件。一开始把端点都写在同一个文件时,中间件正常工作;但拆分每个端点到单独文件后,中间件无法记录URL,浏览器也看不到预期响应。本人有Java开发经验,刚接触TypeScript,需要解决这个问题,实现浏览器显示响应、控制台记录访问URL的目标。

文件结构

文件结构截图

原代码

index.ts

import express from 'express';
import logger from './utilities/logger';
import route from './routes/index'

const app = express();
const port = 3002;

app.use('/sport', route)

app.listen(port, () => {
  console.log(`server started at http://localhost:${port}`);
});

logger.ts

import express from 'express';

const logger = (req: express.Request, res: express.Response, next: Function): 
void => {
    const url = req.url;
    console.log(`${url} was visited - hello`);
    // next();
}

export default logger;

routes/index.ts

import express from 'express';
import football from './api/football'
import basketball from './api/basketball'
import skiing from './api/skiing'

const route = express.Router();

route.get('/', (_req, _res) => {
    _res.send("Main route file");
});

route.use('/basketball', basketball);
route.use('/football', football);
route.use('/skiing', skiing);

export default route;

basketball.ts

import express from 'express';
import logger from '../../utilities/logger';

const route = express.Router();

route.get('/', logger,(_req, _res) => {
    _res.send('bball!');
});

export default route;

football.ts

import express from 'express';
import logger from '../../utilities/logger';

const route = express.Router();

route.get('/', logger,(_req, _res) => {
    _res.send('footie!');
});

export default route;

问题原因

核心问题在logger.ts里:next()被注释掉了。Express中间件的核心逻辑是,处理完自身任务后必须调用next(),才能把请求传递给后续的处理函数(比如路由里的响应发送逻辑)。如果不调用next(),请求会被挂起,既不会触发后续的响应输出,也不会继续处理流程,导致浏览器一直等待响应,同时后续逻辑也无法执行。

另外,原代码里用req.url只能拿到当前路由层级的路径(比如访问/sport/basketball时,req.url是/),如果想记录完整的访问路径,应该用req.originalUrl。

解决方案

1. 修复logger中间件

取消next()的注释,同时把req.url改为req.originalUrl以记录完整路径:

import express from 'express';

const logger = (req: express.Request, res: express.Response, next: express.NextFunction): void => {
    const url = req.originalUrl;
    console.log(`${url} was visited - hello`);
    next(); // 必须调用next传递请求
}

export default logger;

2. 优化路由结构(可选)

如果想让logger对所有请求生效,不用在每个路由文件里单独引入,可以在index.ts全局挂载中间件,这样所有请求都会经过logger:

import express from 'express';
import logger from './utilities/logger';
import route from './routes/index'

const app = express();
const port = 3002;

app.use(logger); // 全局挂载,所有请求都会触发logger
app.use('/sport', route)

app.listen(port, () => {
  console.log(`server started at http://localhost:${port}`);
});

此时,各个路由文件可以去掉logger的引入,简化代码,比如basketball.ts:

import express from 'express';

const route = express.Router();

route.get('/', (_req, _res) => {
    _res.send('bball!');
});

export default route;

测试效果

访问http://localhost:3002/sport/basketball,控制台会输出/sport/basketball was visited - hello,浏览器显示bball!;访问http://localhost:3002/sport/football,控制台输出对应完整URL,浏览器显示footie!,完全符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 01:23:20