Express中间件的原理及实现

在Node开发中免不了要使用框架,比如expresskoakoa2拿使用的最多的express来举例子开发中肯定会用到很多类似于下面的这种代码
var express = require('express'); var app = express(); app.listen(3000, function () { console.log('listen 3000...'); }); app.use(middlewareA); app.use(middlewareB); app.use(middlewareC); 
对我要说的就是app.use()为什么要说这个?因为面试时被问到了。。。
哦 你用过Express啊 来来来 那你说说app.use的原理是什么?
一脸懵逼...0.0
app.use()就是通常所说的使用中间件那中间件是什么呢?它又有啥用呢?

中间件 middleware

一个请求发送到服务器后,它的生命周期是 先收到request(请求),然后服务端处理,处理完了以后发送response(响应)回去而这个服务端处理的过程就有文章可做了,想象一下当业务逻辑复杂的时候,为了明确和便于维护,需要把处理的事情分一下,分配成几个部分来做,而每个部分就是一个中间件
node.js - express 框架中的app.use是什么作用? - SegmentFault
app.use 加载用于处理http请求的middleware(中间件),当一个请求来的时候,会依次被这些 middlewares处理。中间件执行的顺序是你定义的顺序

那中间件到底是个什么东西呢?

中间件其是一个函数,在响应发送之前对请求进行一些操作
function middleware(req,res,next){ // 做该干的事 // 做完后调用下一个函数 next(); } 
这个函数有些不太一样,它还有一个next参数,而这个next也是一个函数,它表示函数数组中的下一个函数

那函数数组又是什么呢

express内部维护一个函数数组,这个函数数组表示在发出响应之前要执行的所有函数,也就是中间件数组使用app.use(fn)后,传进来的fn就会被扔到这个数组里,执行完毕后调用next()方法执行函数数组里的下一个函数,如果没有调用next()的话,就不会调用下一个函数了,也就是说调用就会被终止

Express中间件的使用

理论部分简单的说了一下,现在来用代码验证一下,注意需要安装一下express
/**
 * express中间件的实现和执行顺序
 *
 * Created by BadWaka on 2017/3/6.
 */
var express = require('express'); var app = express(); app.listen(3000, function () { console.log('listen 3000...'); }); function middlewareA(req, res, next) { console.log('middlewareA before next()'); next(); console.log('middlewareA after next()'); } function middlewareB(req, res, next) { console.log('middlewareB before next()'); next(); console.log('middlewareB after next()'); } function middlewareC(req, res, next) { console.log('middlewareC before next()'); next(); console.log('middlewareC after next()'); } app.use(middlewareA); app.use(middlewareB); app.use(middlewareC); 
输出结果:
 
Express中间件的原理及实现_第1张图片
 
可以看到在执行完下一个函数后又会回到之前的函数执行next()之后的部分
这可以理解为中间件的一个特性吧现在可以说已经明白Express的中间件是什么了,以及app.use的用法了,下面就来自己实现一下吧

实现简单的Express中间件

/**
 * 仿照express实现中间件的功能
 *
 * Created by BadWaka on 2017/3/6.
 */

var http = require('http'); /** * 仿express实现中间件机制 * * @return {app} */ function express() { var funcs = []; // 待执行的函数数组 var app = function (req, res) { var i = 0; function next() { var task = funcs[i++]; // 取出函数数组里的下一个函数 if (!task) { // 如果函数不存在,return return; } task(req, res, next); // 否则,执行下一个函数 } next(); } /** * use方法就是把函数添加到函数数组中 * @param task */ app.use = function (task) { funcs.push(task); } return app; // 返回实例 } // 下面是测试case var app = express(); http.createServer(app).listen('3000', function () { console.log('listening 3000....'); }); function middlewareA(req, res, next) { console.log('middlewareA before next()'); next(); console.log('middlewareA after next()'); } function middlewareB(req, res, next) { console.log('middlewareB before next()'); next(); console.log('middlewareB after next()'); } function middlewareC(req, res, next) { console.log('middlewareC before next()'); next(); console.log('middlewareC after next()'); } app.use(middlewareA); app.use(middlewareB); app.use(middlewareC); 
JS是一门神奇的语言,这里用到了两个闭包,并且给app这个函数添加了一个use方法,函数也是可以有属性的原理就是每调用一次use,就把传进来的函数扔到express内部维护的一个函数数组中去测试结果:
 
Express中间件的原理及实现_第2张图片
 
ok,相信对Express中间件的原理已经有所了解了,koa和koa2中间件的原理其实也是一样的




转自:https://www.jianshu.com/p/797a4e38fe77

转载于:https://www.cnblogs.com/donve/p/10265326.html

你可能感兴趣的:(Express中间件的原理及实现)