博客
关于我
nodejs 中间件理解
阅读量:797 次
发布时间:2023-02-16

本文共 3505 字,大约阅读时间需要 11 分钟。

中间件概念

在Node.js环境中,中间件的概念主要用于封装处理Http请求的细节功能。每次Http请求通常会涉及诸多工作流程,如日志记录、IP过滤、查询字符串解析、Cookie处理等。然而,这些基础设施的处理往往会让开发者分心,影响业务逻辑的实现。因此,引入中间件的目的是为了隔离和简化基础设施与业务逻辑之间的交互,提升开发效率。

中间件的工作原理类似于Java中的过滤器机制。在实际的业务处理之前,中间件会被调用进行预处理。其工作流程可以通过下图所示的模型来理解。

中间件机制核心实现

中间件的核心作用是处理从请求开始到响应结束的整个流程。一个基本的中间件形式可以表示为:

const middleware = (req, res, next) => {  // TODO  next()}

通过以下两种方式的实现,可以更直观地理解中间件的工作机制。

方式一:简单的中间件定义

定义三个简单的中间件:

const middleware1 = (req, res, next) => {  console.log('middleware1 start')  next()}const middleware2 = (req, res, next) => {  console.log('middleware2 start')  next()}const middleware3 = (req, res, next) => {  console.log('middleware3 start')  next()}

将中间件组合使用:

const middlewares = [middleware1, middleware2, middleware3]function run(req, res) {  const next = () => {    const middleware = middlewares.shift()    if (middleware) {      middleware(req, res, next)    }  }  next()}run()

执行结果:

middleware1 startmiddleware2 startmiddleware3 start

当中间件包含异步操作时,需要在异步流程完成后才能调用next()方法。例如:

const middleware2 = (req, res, next) => {  console.log('middleware2 start')  new Promise(resolve => {    setTimeout(() => resolve(), 1000)  }).then(() => {    next()  })}

执行结果与之前一致,但middleware3会在middleware2异步完成后执行。

解决方式二:使用Promise优化

为了在异步操作后正确调用next(),可以将next()方法的返回值封装为Promise对象。改写run()方法:

function run(req, res) {  const next = () => {    const middleware = middlewares.shift()    if (middleware) {      return Promise.resolve(middleware(req, res, next))    } else {      return Promise.resolve("结束")    }  }  next()}

中间件的调用方式需改写为:

const middleware1 = (req, res, next) => {  console.log('middleware1 start')  return next().then(() => {    console.log('middleware1 end')  })}const middleware2 = (req, res, next) => {  console.log('middleware2 start')  return next().then(() => {    console.log("2", result)    return 'middleware2 end'  })}const middleware3 = (req, res, next) => {  console.log('middleware3 start')  return next().then(() => {    console.log("3", result)    return 'middleware3 end'  })}

运行结果:

middleware1 startmiddleware2 startmiddleware3 start

async/await实现

使用async/await方式实现中间件:

const middleware1 = async (req, res, next) => {  console.log('middleware1 start')  let result = await next()  console.log("1", result)}const middleware2 = async (req, res, next) => {  console.log('middleware2 start')  let result = await next()  console.log("2", result)  return 'middleware2 end'}const middleware3 = async (req, res, next) => {  console.log('middleware3 start')  let result = await next()  console.log("3", result)  return 'middleware3 end'}

运行结果:

middleware1 startmiddleware2 startmiddleware3 start

koa2框架中的洋葱圈模型

Koa2框架的中间件实现更加优雅,采用洋葱圈模型。核心代码如下:

function compose(middleware) {  if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')  for (const fn of middleware) {    if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')  }  return function(context, next) {    let index = -1    return dispatch(0)    function dispatch(i) {      if (i <= index) return Promise.reject(new Error('next() called multiple times'))      index = i      let fn = middleware[i]      if (i === middleware.length) fn = next      if (!fn) return Promise.resolve()      try {        return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))      } catch (err) {        return Promise.reject(err)      }    }  }}

参考来源:Koa2框架官方文档

总结

本文介绍了中间件的概念、引入的必要性以及其核心实现机制。中间件机制使得Web应用具有良好的可扩展性和组合性。每个中间件应保持职责单一,确保代码高效且必要时可缓存数据。在实际应用中,需根据具体路由选择中间件,以提升整体应用性能和用户体验。

转载地址:http://evjfk.baihongyu.com/

你可能感兴趣的文章
ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
查看>>
NHibernate学习[1]
查看>>
NHibernate异常:No persister for的解决办法
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
查看>>
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_根据binlog实现数据实时delete同步_实际操作04---大数据之Nifi工作笔记0043
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置binlog_使用处理器抓取binlog数据_实际操作01---大数据之Nifi工作笔记0040
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_配置数据路由_实现数据插入数据到目标数据库_实际操作03---大数据之Nifi工作笔记0042
查看>>
NIFI从MySql中离线读取数据再导入到MySql中_03_来吧用NIFI实现_数据分页获取功能---大数据之Nifi工作笔记0038
查看>>
NIFI从PostGresql中离线读取数据再导入到MySql中_带有数据分页获取功能_不带分页不能用_NIFI资料太少了---大数据之Nifi工作笔记0039
查看>>
NIFI同步MySql数据_到SqlServer_错误_驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server_Navicat连接SqlServer---大数据之Nifi工作笔记0047
查看>>
Nifi同步过程中报错create_time字段找不到_实际目标表和源表中没有这个字段---大数据之Nifi工作笔记0066
查看>>
NIFI大数据进阶_FlowFile拓扑_对FlowFile内容和属性的修改删除添加_介绍和描述_以及实际操作---大数据之Nifi工作笔记0023
查看>>
NIFI大数据进阶_NIFI的模板和组的使用-介绍和实际操作_创建组_嵌套组_模板创建下载_导入---大数据之Nifi工作笔记0022
查看>>
NIFI大数据进阶_NIFI监控的强大功能介绍_处理器面板_进程组面板_summary监控_data_provenance事件源---大数据之Nifi工作笔记0025
查看>>
NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
查看>>
NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
查看>>