广告
返回顶部
首页 > 资讯 > 精选 >nodejs中间件Koa和Express有什区别
  • 116
分享到

nodejs中间件Koa和Express有什区别

2023-06-06 12:06:10 116人浏览 八月长安
摘要

这篇文章将为大家详细讲解有关nodejs中间件Koa和Express有什区别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Koa用起来非常方便——比之express,它“完美中间件”的设计让功能之间看起来

这篇文章将为大家详细讲解有关nodejs中间件Koa和Express有什区别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

Koa用起来非常方便——比之express,它“完美中间件”的设计让功能之间看起来非常简洁!笔者在项目中就曾这样使用过:

const Koa=require('koa')const app=new Koa()const Router=require('koa-router')const router=new Router()const cors=require('koa2-cors')const koaBody=require('koa-body')const ENV='test-mpin2'app.use(cors({origin:['Http://localhost:9528'],   // 也可以写为:['*']credentials:true}))app.use(koaBody({multipart:true}))app.use(async(ctx,next)=>{console.log('访问全局中间件')ctx.state.env=ENV   // 全局缓存await next()})const playlist=require('./controller/playlist.js')router.use('/playlist',playlist.routes())const blog=require('./controller/blog.js')router.use('/blog',blog.routes())app.use(router.routes()).use(router.allowedMethods())app.listen(3000,()=>{console.log('服务已开启')})

它将路由router抽离出去作为单独的中间件使用,则app只负责全局处理。还比如:

// 最外层中间件,可以用于兜底 Koa 全局错误app.use(async (ctx, next) => {  try {    // 执行下一个中间件    await next();  } catch (error) {    console.log(`[koa error]: ${error.message}`)  }});// 第二层中间件,可以用于日志记录app.use(async (ctx, next) => {  const { req } = ctx;  console.log(`req is ${JSON.stringify(req)}`);  await next();  console.log(`res is ${JSON.stringify(ctx.res)}`);});

简单实现一个Koa吧!

如上代码,我们看 Koa 实例,通过use方法注册和串联中间件,其源码的简单实现可以表述为:

use(fn) {    this.middleware.push(fn);    return this;}

我们将中间件存储到this.middleware数组中,那么中间件是如何被执行的呢?参考下面源码:

// 通过 createServer 方法启动一个 node.js 服务listen(...args) {    const server = http.createServer(this.callback());    server.listen(...args);}

Koa 框架通过 http 模块的 createServer 方法创建一个 node.js 服务,并传入 this.callback() 方法, callback源码简单实现如下:

callback(){const fn=compose(this.middlewareList)return (req,res)=>{const ctx=createContext(req,res)return this.handleRequest(ctx,fn)}}handleRequest(ctx, fn) {    const onerror = err => ctx.onerror(err);    // 将 ctx 对象传递给中间件函数 fn    return fn(ctx).catch(onerror);}

如上代码,我们将 Koa 一个中间件组合和执行流程梳理为以下步骤:

  • 通过一个方法(我们称为compose)组合各种中间件,返回一个中间件组合函数fn

  • 请求过来时,会先调用handleRequest方法,该方法完成:

    • 调用createContext方法,对该次请求封装出一个ctx对象;

    • 接着调用this.handleRequest(ctx, fn)处理该次请求。

其中,核心过程就是使用compose方法组合各种中间件 —— 这是一个单独的方法,它应该不受Koa其余方法的约束。其源码简单实现为:

// 组合中间件// 和express中的next函数意义一样function compose(middlewareList){// return function意思是返回一个函数return function(ctx,next){// 各种中间件调用的逻辑function dispatch(i){const fn=middlewareList[i] || nextif(fn){try{// koa中都是async,其返回的是一个promise(对象)return Promise.resolve(fn(ctx,function next(){return dispatch(i+1)}))}catch(err){return Promise.reject(err)}}else{return Promise.resolve()}}return dispatch(0)}}

其功能可以表示为这样(非源码):

async function middleware1() {  //...  await (async function middleware2() {    //...    await (async function middleware3() {      //...    });    //...  });  //...}

到这里我们其实可以“初窥”其原理,有两点:

  • Koa 的中间件机制被社区形象地总结为洋葱模型;

所谓洋葱模型,就是指每一个 Koa 中间件都是一层洋葱圈,它即可以掌管请求进入,也可以掌管响应返回。换句话说:外层的中间件可以影响内层的请求和响应阶段,内层的中间件只能影响外层的响应阶段。

  • dispatch(n)对应第 n 个中间件的执行,在使用中即第 n 个中间件可以通过await next()来“插入”执行下一个中间件,同时在最后一个中间件执行完成后,依然有恢复执行的能力。即:通过洋葱模型,await next()控制调用后面的中间件,直到全局没有可执行的中间件且堆栈执行完毕,最终“原路返回”至第一个执行next的中间件。这种方式有个优点,特别是对于日志记录以及错误处理等全局功能需要非常友好。

Koa1 的中间件实现利用了 Generator 函数 + co 库(一种基于 Promise 的 Generator 函数流程管理工具),来实现协程运行。本质上,Koa v1 中间件和 Koa v2 中间件思想是类似的,只不过 Koa v2 改用了 Async/Await 来替换 Generator 函数 + co 库,整体实现更加巧妙,代码更加优雅。—— from《狼书》

经过上述部分源码的描述,我们就可以采用es6的方式将其组合起来:

// myKoa.js文件const http=require('http')function compose(){}   //见上class LikeKoa2{constructor() {    this.middlewareList=[]}use(){}   //见上// 把所有的req,res属性、事件都交给ctx(这里只是简写)createContext(req,res){const ctx={req,res}// 比如ctx.query=req,queryreturn ctx}handleRequest(){}   //见上callback(){}   //见上listen(){}   //见上}// koa和express的不同之一:// express在调用时直接调用函数:const app=express();所以暴露出去new过的对象——具体见下面链接中代码// 但是koa调用时以类的方式:const app=new Koa();所以直接暴露出去module.exports=LikeKoa2

那use方法和其余方法并不相通,它是如何被执行的呢?执行了createServer后是不是相当于建立了一个通道、挂载了一个监听函数呢?
这一点恐怕就要到Node的源码中一探究竟了…


对比 Koa,聊聊 Express 原理

说起 Node.js 框架,我们一定忘不了 Express —— 不同于 Koa,它继承了路由、静态服务器和模板引擎等功能,虽然比之Koa显得“臃肿”了许多,但看上去比 Koa 更像是一个框架。通过学习 Express 源码,笔者简单的总结了它的工作机制:

  • 通过app.use方法注册中间件。

  • 一个中间件可以理解为一个 Layer 对象,其中包含了当前路由匹配的正则信息以及 handle 方法。

  • 所有中间件(Layer 对象)使用stack数组存储起来。

  • 当一个请求过来时,会从 req 中获取请求 path,根据 path 从stack中找到匹配的 Layer,具体匹配过程由router.handle函数实现。

  • router.handle函数通过next()方法遍历每一个 layer 进行比对:

    • next()方法通过闭包维持了对于 Stack Index 游标的引用,当调用next()方法时,就会从下一个中间件开始查找;

    • 如果比对结果为 true,则调用layer.handle_request方法,layer.handle_request方法中会调用next()方法 ,实现中间件的执行。

通过上述内容,我们可以看到,Express 其实是通过 next() 方法维护了遍历中间件列表的 Index 游标,中间件每次调用next()方法时,会通过增加 Index 游标的方式找到下一个中间件并执行。它的功能就像这样:

((req, res) => {  console.log('第一个中间件');  ((req, res) => {    console.log('第二个中间件');    (async(req, res) => {      console.log('第三个中间件');      await sleep(2000)      res.status(200).send('hello')    })(req, res)    console.log('第二个中间件调用结束');  })(req, res)  console.log('第一个中间件调用结束')})(req, res)

如上代码,Express 中间件设计并不是一个洋葱模型,它是基于回调实现的线形模型,不利于组合,不利于互操,在设计上并不像 Koa 一样简单。而且业务代码有一定程度的侵扰,甚至会造成不同中间件间的耦合。

express的简单实现笔者已上传至腾讯微云,需要者可自行查看&下载:express的简单实现

关于“nodejs中间件Koa和Express有什区别”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: nodejs中间件Koa和Express有什区别

本文链接: https://www.lsjlt.com/news/246990.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • nodejs中间件Koa和Express有什区别
    这篇文章将为大家详细讲解有关nodejs中间件Koa和Express有什区别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Koa用起来非常方便——比之express,它“完美中间件”的设计让功能之间看起来...
    99+
    2023-06-06
  • nodejs里的koa-static中间件是什么
    这篇文章主要介绍“nodejs里的koa-static中间件是什么”,在日常操作中,相信很多人在nodejs里的koa-static中间件是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”nodejs里的k...
    99+
    2023-06-07
  • node.js express和koa中间件机制和错误处理机制
    目录一、前言二、中间件问题解析三、错误逻辑捕获3.1 express的错误捕获逻辑3.2 同步逻辑错误获取的底层逻辑3.3 异步逻辑错误获取的底层逻辑3.4 koa的错误获取逻辑一、...
    99+
    2022-11-13
  • python和nodejs之间有哪些区别
    这篇文章主要为大家展示了“python和nodejs之间有哪些区别”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python和nodejs之间有哪些区别”这篇文...
    99+
    2022-10-19
  • nodejs和JavaScript有什么区别
    这期内容当中小编将会给大家带来有关nodejs和JavaScript有什么区别,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。JavaScript的特点1.JavaScript主要用来向HTML页面添加交互...
    99+
    2023-06-14
  • typescript和nodejs有什么区别
    这篇文章将为大家详细讲解有关typescript和nodejs有什么区别,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。区别:1、typescript是微软开...
    99+
    2022-10-19
  • nodejs中path.join和path.resolve的有什么区别
    这篇文章主要讲解了“nodejs中path.join和path.resolve的有什么区别”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs中pat...
    99+
    2022-10-19
  • node Express框架中的res.send()和res.end()有什么区别
    本篇内容主要讲解“node Express框架中的res.send()和res.end()有什么区别”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“node Ex...
    99+
    2022-10-19
  • python和nodejs对比有什么区别
    python和nodejs对比的区别有:1、python中需要使用virtualenv来分割管理依赖包,而nodejs中通过NPM包管理;2、python中使用from/import进行引入模块;而nodejs引入的其他模块在本模块内都有局...
    99+
    2022-10-07
  • Linux中[./]和[/]和[.]之间的区别有什么
    本篇文章为大家展示了Linux中[./]和[/]和[.]之间的区别有什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。/是指根目录,就和Windows的我的电脑那个位置差不多。./是指用户所在的当前...
    99+
    2023-06-28
  • Shell $*和$@之间有什么区别
    本篇内容主要讲解“Shell $*和$@之间有什么区别”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Shell $*和$@之间有什么区别”吧!$* 和 $@ 都表示传递给函数或脚本的所有参数,本...
    99+
    2023-06-09
  • Java中Sring和StringBuffer、StringBuilder间有什么区别
    这篇“Java中Sring和StringBuffer、StringBuilder间有什么区别”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一...
    99+
    2023-06-27
  • mysql中utf8和utf8mb4之间有什么区别
    小编给大家分享一下mysql中utf8和utf8mb4之间有什么区别,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、简介MyS...
    99+
    2022-10-18
  • sql中delete和truncate之间有什么区别
    这篇文章给大家分享的是有关sql中delete和truncate之间有什么区别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在SQL中delete命令和truncate命令都可用...
    99+
    2022-10-18
  • javascript和js之间有什么区别
    这篇文章给大家分享的是有关javascript和js之间有什么区别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。javascript和js之间没有区别;js是javascript的简称,意思是一样的。javasc...
    99+
    2023-06-14
  • php fgetc()和fgets()间有什么区别
    本教程操作环境:windows7系统、PHP7.1版、DELL G3电脑在php中,fgetc()和fgets()都可以从文件中读取数据,但也有区别,下面介绍一下。php fgetc()和fgets()的区别1、功能区别fgetc():从打...
    99+
    2014-07-22
    php fgetc() fgets()
  • JDBC和ODBC之间有什么区别
    这篇文章将为大家详细讲解有关JDBC和ODBC之间有什么区别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。JDBC和ODBC都是API(应用程序编程接口),它帮助客户端的...
    99+
    2022-10-18
  • QueueUserWorkItem() 和 BeginInvoke() 之间有什么区别
    QueueUserWorkItem()和BeginInvoke()都是用来在线程池中执行委托的方法,但它们有一些区别。1. 参数类型...
    99+
    2023-09-26
    区别
  • URL和URI之间有什么区别
    URL和URI之间的区别是:1、URI是用于标识互联网上的资源的字符串序列,而URI并不关注资源的位置,而只关注它的标识符;2、URL提供了关于资源在互联网上位置的详细信息,而URI是一种更广义的概念,不仅涵盖了URL,还包括了用于标识资源...
    99+
    2023-08-14
  • Spring和SpringBoot之间有什么区别
    这篇文章主要介绍了Spring和SpringBoot之间有什么区别,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Spring是什么?简单地说,Spring框架为开发Java应...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作