Node.js技术栈的web框架,以express(v4.x)和koa(2
)最为流行。

1. 线性中间件

先看例子

app.use(function (req, res, next) {
  console.log("Middleware1 start", new Date());
  next();
  console.log("Middleware1 end", new Date());
});
app.use(function (req, res, next) {
  console.log("Middleware2 start", new Date());
  next();
  console.log("Middleware2 end", new Date());
});

访问一个routing,大家觉得server端日志输出会是什么呢?

Middleware1 start 2021-03-27T01:56:17.872Z
Middleware2 start 2021-03-27T01:56:17.874Z
Middleware2 end 2021-03-27T01:56:17.875Z  
Middleware1 end 2021-03-27T01:56:17.875Z  

洋葱模型啊!为什么又说是线性模型呢?我们稍微调整一下我们处理routing的代码,做一个假的异步处理,让其1秒钟之后返回,e.g.

router.get("/", function (req, res, next) {
  setTimeout(() => {
    console.log("index router", new Date());
    res.render("index", { title: "Express" });
  }, 1000);
});

那么这次再访问routing,输出是什么呢?

Middleware1 start 2021-03-27T01:56:17.872Z
Middleware2 start 2021-03-27T01:56:17.874Z
Middleware2 end 2021-03-27T01:56:17.875Z  
Middleware1 end 2021-03-27T01:56:17.875Z  
index router 2021-03-27T01:56:18.876Z

注意server端日志,2次middleware的end日志优先于index中的日志返回,也就是说,middleware中, next中如果有异步处理,那么有可能会是优先执行next()之后代码。当然一般情况下,我们没有这种需求,所以一般来说,express的中间件,next()之后不要再写任何东西,因为是没有意义的。总之,Express 中间件实现是基于 Callback 回调函数同步的,它不会去等待异步完成。

Express的立即响应(res.send 唯一性)

Express在中间件中,可以直接调用res.send() 返回结果给客户端。如,请求如果没有带token信息,验证中间件可以直接返回401错误,不再继续执行其他操作;

express中,无论是中间件,还是router,调用 res.send() 之后就立即响应了,返回response给客户端。所以要求一次请求,只能由一个res.send。如果执行多次 send 是会报 ERR_HTTP_HEADERS_SENT 错误。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐