博客
关于我
nodejs 中间件理解
阅读量:791 次
发布时间: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/

你可能感兴趣的文章
NIFI大数据进阶_离线同步MySql数据到HDFS_说明操作步骤---大数据之Nifi工作笔记0028
查看>>
NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
查看>>
NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
查看>>
NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
查看>>
NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南002---大数据之Nifi工作笔记0069
查看>>
NIFI集群_内存溢出_CPU占用100%修复_GC overhead limit exceeded_NIFI: out of memory error ---大数据之Nifi工作笔记0017
查看>>
NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
查看>>
NIH发布包含10600张CT图像数据库 为AI算法测试铺路
查看>>
Nim教程【十二】
查看>>
Nim游戏
查看>>
NIO ByteBuffer实现原理
查看>>
Nio ByteBuffer组件读写指针切换原理与常用方法
查看>>
NIO Selector实现原理
查看>>
nio 中channel和buffer的基本使用
查看>>
NIO三大组件基础知识
查看>>
NIO与零拷贝和AIO
查看>>
NIO同步网络编程
查看>>
NIO基于UDP协议的网络编程
查看>>
NIO笔记---上
查看>>
NIO蔚来 面试——IP地址你了解多少?
查看>>