koa中间件的实现原理如何?先来看一个例子。

koa的执行顺序是这样的:

const middleware = async function (ctx, next) {
console.log(1)
await next()
console.log(6)
} const middleware2 = async function (ctx, next) {
console.log(2)
await next()
console.log(5)
} const middleware3 = async function (ctx, next) {
console.log(3)
await next()
console.log(4)
}

会依次打印1,2,3,4,5,6

问题是koa中间件实现原理,也就是洋葱模型的实现原理是什么?

一、问题分析

async await是promise的语法糖,await后面跟一个promise,所以上面的代码可以写成:

const middleware = function (ctx, next) {
console.log(1)
next().then(() => {
console.log(6)
})
} const middleware2 = function (ctx, next) {
console.log(2)
next().then(() => {
console.log(5)
})
} const middleware3 = function (ctx, next) {
console.log(3)
next().then(() => {
console.log(4)
})
}

改成这样更好理解一些,所以流程控制的核心在于next的实现。

next要求调用队列中下一个middleware,当达到最后一个的时候resolve。这样最后面的promise先resolve,一直到第一个,这样就是洋葱模型的顺序了。

二、实现

koa-compose的实现是这样的:

function compose(middleware) {
return function (context, next) {
let index = -1
return dispatch(0) function dispatch(i) {
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)
}
}
}
}

我们把一些参数检查的非核心逻辑去掉了,实现代码就上面那些。每次传入的next都是调用下一个middleware,这样是一个递归的过程,结束条件是最后一个middleware的next是用户传入的。

这里面有一些亮点:

  1. 这是一种尾递归的形式,尾递归的特点是最后返回的值是一个递归的函数调用,这样执行完就会在调用栈中销毁,不会占据调用栈.
  2. 返回的是一个Promise.resolve包装之后的调用,而不是同步的调用,所以这是一个异步递归,异步递归比同步递归的好处是可以被打断,如果中间有一些优先级更高的微任务,那么可以先执行别的微任务
  3. compose是函数复合,把n个middleware复合成一个,参数依然是context和next,这种复合之后依然是一个middleware,还可以继续进行复合。

三、总结

Koa 中间件的实现原理,也就是洋葱模型的实现原理,核心在于next的实现。next需要依次调用下一个middleware,当到最后一个的时候结束,这样后面middleware的promise先resolve,然后直到第一个,这样的流程也就是洋葱模型的流程了。

实现的时候还有一些细节,一个是递归最好做成尾递归的形式,而是用异步递归而不是同步递归,第三就是形式上用函数复合的形式,这样复合之后的中间件还可以继续复合。

koa中间件的实现原理的更多相关文章

  1. koa中间件系统原理及koa+orm2实践。

    koa是由 Express 原班人马打造的新的web框架.套用其官方的说法:Koa 应用是一个包含一系列中间件 generator 函数的对象. 这些中间件函数基于 request 请求以一个类似于栈 ...

  2. 【nodejs原理&源码赏析(2)】KOA中间件的基本运作原理

    [摘要] KOA中间件的基本运作原理 示例代码托管在:http://www.github.com/dashnowords/blogs 在中间件系统的实现上,KOA中间件通过async/await来在不 ...

  3. Koa中间件(middleware)级联原理

    前言 上次看到了koa-compose的代码,今天来说一下koa中间件的级联以及工作原理. 中间件工作原理 初始化koa实例后,我们会用use方法来加载中间件(middleware),会有一个数组来存 ...

  4. KOA中间件的基本运作原理

    示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 华为云社区地址:[你要的前端打怪升级指南] 在中 ...

  5. koa 中间件

    什么是 Koa 的中间件 通俗的讲:中间件就是匹配路由之前或者匹配路由完成做的一系列的操作,我们就可以 把它叫做中间件. 在express中间件(Middleware)是一个函数,它可以访问请求对象( ...

  6. Koa - 中间件(理解中间件、实现一个验证token中间件)

    前言 Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的. 当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件.当在下游没有更多的中间件执行后 ...

  7. Koa 中间件的执行

    Node.js 中请求的处理 讨论 Koa 中间件前,先看原生 Node.js 中是如何创建 server 和处理请求的. node_server.js const http = require(&q ...

  8. laravel中间件的实现原理

    中间件的实现原理 运用 array_reduce 以及 call_user_func 实现 interface Middleware { public static function handle(C ...

  9. koa 基础(八)koa 中间件的执行顺序

    1.koa 中间件的执行顺序 app.js /** * koa 中间件的执行顺序 */ // 引入模块 const Koa = require('koa'); const router = requi ...

  10. Koa 中间件的执行顺序

    中间件工作原理 初始化koa实例后,我们会用use方法来加载中间件(middleware),会有一个数组来存储中间件,use调用顺序会决定中间件的执行顺序. 每个中间件都是一个函数(不是函数将报错), ...

随机推荐

  1. HCIA-ICT实战基础11-网络地址转换NAT&NAPT

    HCIA-ICT实战基础-网络地址转换 目录 NAT概述 静态NAT 动态NAT NAPT.Easy-IP NAT Server 扩展 NAT ALG 扩展 双向NAT 扩展 重叠NAT转换方式 1 ...

  2. Docker学习——Dockerfile 指令详解(五)

    我们已经介绍了 FROM (指定基础镜像) , RUN(执行命令) ,还提及了 COPY , ADD ,其实 Dockerfile 功能很强大,它提供了十多个指令.下面我们继续讲解其他的指令. COP ...

  3. FastReport和RDLC报表

    最近在做报表的时候第一次接触到RDLC报表,对比于之前使用的FastReport报表来说,在使用体验上个人目前感觉RDLC灵活性相对较差,尤其是表格的格式多样的时候,不易修改.RDLC应用于格式简单的 ...

  4. 【逆向】x64dbg设置条件断点 比较内存字符串是否相等

    前言 在OD中可以设置条件断点,通过表达式对字符串数据进行比较,比如在CreateFile打开某个特定文件的时候让调试器中断.但是在x32dbg.x64dbg中因为表达式只支持整数,不支持字符串和其它 ...

  5. 类继承(c++ primer plus)课后习题

    第一题: // base class class Cd { // represents a CD disk private: char performers[50]; char label[20]; ...

  6. 结对作业——考研咨询APP

    结对作业--考研资讯系统   102陈同学105潘同学108苏同学 (排版:Markdown) 一.需求分析(NABCD模型) 1. N(Need 需求): 1)想知道每个专业考研可以考哪个专业2)想 ...

  7. Python测试——安装篇总结

    测试用到的工具自己知道的有: 写脚本类:sublime  ,PyCharm,Eclipse+PyDev,目前我知道的只有这么多,大家知道的肯定还有很多,欢迎留言哈 录制脚本类:火狐自带的seleniu ...

  8. login_while

    # -*- coding: utf-8 -*- # @Time : 2020/7/25 22:45 # @Author : Breeze # @FileName: login_while.py use ...

  9. Android 自定义View (三)

    一.前言 上节 讲解了旋转圆环基本的实现方法.本文将在此基础上进一步改进,在属性文件中自定义控件属性,避免代码中显式调用setXXX() 方法. 二.流程 首先,在资源文件 values 中新建一个 ...

  10. nodejs 利用URL和querystring获取get查询参数

    为深入理解request的get url信息及参数传递,利用URL和querystring获取对应的信息,测试成功,记录如下: 1.编写server.js文件 http=require("h ...