关于异步中间件的处理
约 693 字大约 2 分钟
2025-03-30
在 Koa 中,关于中间件的执行顺序和 next()
的调用,有以下关键点需要理解:
一、中间件不一定要等待当前操作完成才调用 next()
你完全可以在当前中间件中的异步操作完成之前就调用 next()
,让后续中间件先执行。这是 Koa 中间件的一个重要特性,称为"下游"执行。
app.use(async (ctx, next) => {
console.log("1. 开始");
// 不等待,直接进入下一个中间件
await next();
// 这里会在所有后续中间件完成后才执行(上游)
console.log("1. 结束");
});
app.use(async (ctx, next) => {
console.log("2. 开始");
await someAsyncOperation(); // 长时间异步操作
console.log("2. 结束");
});
输出结果:
1. 开始
2. 开始
(异步操作等待...)
2. 结束
1. 结束
二、控制执行流程的三种模式
1、先执行当前逻辑,再进入下一个中间件
app.use(async (ctx, next) => {
await doSomething(); // 先完成自己的任务
await next(); // 再进入下一个中间件
});
2、先进入下一个中间件,再执行当前逻辑
app.use(async (ctx, next) => {
await next(); // 先让后续中间件执行
await doSomething(); // 再执行自己的收尾工作
});
3、并行执行 不推荐
不推荐这样去操作,比较难控制,容易让逻辑变复杂。
app.use(async (ctx, next) => {
const promise1 = doSomething();
const promise2 = next(); // 注意这种用法需要谨慎
await Promise.all([promise1, promise2]);
});
三、典型应用场景
1、日志记录中间件
app.use(async (ctx, next) => {
const start = Date.now();
await next(); // 先让请求处理完成
const duration = Date.now() - start;
console.log(`${ctx.method} ${ctx.url} - ${duration}ms`);
});
2、提前响应
app.use(async (ctx, next) => {
if (ctx.path === "/healthcheck") {
ctx.body = "OK"; // 直接响应,不调用next()
return;
}
await next();
});
四、重要注意事项
如果不调用
next()
,后续中间件将不会执行app.use(async (ctx, next) => { ctx.body = "拦截响应"; // 不调用next,后续中间件被跳过 });
调用但不等待
next()
可能导致意外行为:app.use(async (ctx, next) => { next(); // 没有await,后续中间件与当前代码并行执行 console.log("这可能先于后续中间件执行"); });
错误处理:必须在异步操作中使用 try-catch
app.use(async (ctx, next) => { try { await next(); } catch (err) { // 处理错误 } });
五、总结
Koa 中间件的 next()
调用时机非常灵活:
- 可以立即调用(不等待当前操作完成)
- 可以后期调用(等待某些条件满足)
- 甚至可以选择性调用(根据条件决定是否进入后续中间件)
这种灵活性使得你可以实现各种复杂的请求处理流程,如:
- 前置验证
- 请求计时
- 条件管道
- 并行处理等
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于