express 的中间件也可以形成“洋葱圈”模型,在 next 调用后写的代码同样会执行到,不过express中一般不会这么做,因为 express的response一般在最后一个中间件,那么其它中间件 next() 后的代码已经影响不到最终响应结果了 求大佬解释一下 这句话什么意思?
我的理解是洋葱模型针对的是一次请求,也就是一次请求贯穿所有的中间件,express中可以通过res.end()返回一次请求,但是koa中即使ctx.body,也会等到所有中间件执行完毕后返回请求。可以看一下koa的处理代码, handleRequest(ctx, fnMiddleware) { const res = ctx.res; res.statusCode = 404; const onerror = err => ctx.onerror(err); //错误处理 const handleResponse = () => respond(ctx); //请求响应函数 onFinished(res, onerror); //监听response响应完成后,做资源清理工作 return fnMiddleware(ctx).then(handleResponse).catch(onerror); // fnMiddleware 返回Promise Promise.catch 捕获错误 }
都是回调写法,只是express写死了router里面加一层 而 koa2可以通过middleware无限串起来 这样导致同样的业务 koa2在middleware膨胀得情况下,性能要比express低
koa运行原理
/**
*middleware 数组
*/
const compose = async (middleware)=>{
if(!Array.isArray(middleware)){
throw new TypeError('Middleware stack must be an Array!')
}
return async (ctx,next)=>{
let index = 0
await dispatch(0)
async function dispatch(i){
if(index > i){
throw new Error('next() called multiple times')
}
index = i
let fn = middleware[i]
if(i === middleware.length){
fn = next
}
if(fn){
try{
await fn(ctx,async ()=>dispatch(i+1))
}catch(err){
console .error(err)
ctx.throw(500,'server error')
}
}
}
}
}
module.exports =compose