最近在学习node.js过程中,发现到实际项目中,有很多琐碎的细节工作要完成,对于开发者而已,开发者只需要注重其中的业务开发上,不用接触到那么多细节的处理,以达到提升开发效率的目的,这时候我们就要引入中间件了。
早先前的中间件定义是在操作系统上为应用软件提供服务的计算机软件,它既不是操作系统,也不是应用软件,只是为了应用软件更好,更方便地使用底层服务。
如今node.js中中间件的含义,就是为了封装HTTP请求中细节处理的中间件,就是一种功能的封装方式,使开发者可以脱离这部分细节,专注在业务上。
中间件像个过滤器,就是进入具体业务之前,先让过滤器处理。然后再响应。
每个中间件处理掉相对简单的逻辑,多个合起来,最终汇成了强大的框架基础!
我们需要提供一种机制,就是再当前中间件处理完成后,通知下一个中间件执行。这里通过递归方式方式实现。执行完TODO后,通过next() 告知下一个中间件执行。如果不调用next函数,请求就在这个中间件中终止了。
//定义中间件 const m1 = function (req, res, next) { //TODO next() } const m2 = function (req, res, next) { //TODO next() } //中间件集合 const middlewares = [m1, m2] //定义执行中间件的方法 function useApp (req, res) { const next = () => { // 获取第一个中间件 const middleware = middlewares.shift() if (middleware) { middleware(req, res, next) } } next() } //执行 useApp()
这里执行完第一个中间件后,再调用next()执行下一个中间件,这样就会执行所有的中间,请求到响应就不会停下来。
那问题来了 要是有的中间件是异步的怎么办? koa2中就要用到es7新特性,async await,这样可以将中间件的方法改成
//定义中间件 const m1 = async (req, res, next) { //TODO await next() } const m2 = function (req, res, next) { //TODO await next() }
注意,这时候通过async await,使中间件的值变成了Promise对象,这时候执行中间件的方法也要改变。
//定义执行中间件的方法 function useApp (req, res) { const next = () => { // 获取第一个中间件 const middleware = middlewares.shift() if (middleware) { Promise.resolve(middleware(req, res, next)) } } next() }
koa2中使用的就是asyn await方法使用中间件,欣赏下koa2的洋葱模型
了解完中间件后就自己写一个中间件吧,这里这个中间件是将返回值格式封装起来,这样开发者就不用担心返回值的格式了。
//返回值中间件 const response = () => { return async (ctx, next) => { ctx.empty = arr => { var isnull = [] const req = ctx.request.method == "POST" ? ctx.request.body : ctx.query for (let item of arr) { if (!req[item]) { isnull.push(item) } } if (isnull.length) { ctx.body = { code: -1, msg: '缺少参数' + isnull.join("、") } return true } return false } ctx.suc = (msg, data) => { ctx.body = { code: 1, msg, data } } ctx.err = (msg, err) => { ctx.body = { code: -1, msg, err: err ? err.toString() : '' } } await next() } } module.exports = response
然后在app.js里引用次中间件
app.use(response())
实现业务功能的时候直接就使用以上定义的中间就可以,
ctx.empty:判断参数是否齐全,
ctx.suc:成功时返回值格式
ctx.err:失败时返回的格式
通过这些中间件,我们不知不觉将复杂的事情简化下来。