当前位置: 首页 > 编程日记 > 正文

Koa2和Redux中间件源码研究

一、Koa2中间件源码分析

在Koa2中,中间件被存放在一个数组中。 使用koa中,最常见的就是app.use(fn),use函数部分源码如下所示。首先中间件必须是个函数。若是generator函数,则需要进行转化。最后把该中间件推入middelaware数组中。

constructor() {this.middleware = [];
}
use(fn) {this.middleware.push(fn);
}
复制代码

当调用app.listen函数时,实际上是创建了一个原生http服务器,并执行了Koa自身的callback方法。

listen(...args) {const server = http.createServer(this.callback());return server.listen(...args);
}
复制代码

callback函数中compose是将中间件封装成一个迭代器,按照middleware数组中顺序执行下去,实现了面向切面编程。handleRequest函数则是将req和res封装成ctx,并执行中间件。

callback() {const fn = compose(this.middleware);const handleRequest = (req, res) => {const ctx = this.createContext(req, res);return this.handleRequest(ctx, fn);};return handleRequest;
}
handleRequest(ctx, fnMiddleware) {...return fnMiddleware(ctx).then(handleResponse).catch(onerror);
}
复制代码

compose用来返回一个迭代器函数fnMiddleware,该函数接受两个参数,context和next。因为调用时只向fnMiddleware传入了第一个参数context,所以next参数的值一直是undefined。

首先定义了index,dispatch传入的参数 i 作为每个中间件的调用标志,每次中间件调用next函数都会让index+1,若是中间件多次调用next,则会使index大于等于该标志,就会报错。

然后依次读取中间件数组中的中间件,并将context和封装了调用标志i的dispatch函数传给中间件,就实现了中间件的过程。
当读取完中间件数组后,即i === middleware.length时,将值为是undefined的next传给fn并结束迭代。dispatch函数所有的返回值都是Promise函数,这样就可以实现异步编程。

function compose (middleware) {return function (context, next) {// last called middleware #let index = -1return dispatch(0)function dispatch (i) {if (i <= index) return Promise.reject(new Error('next() called multiple times'))index = ilet fn = middleware[i]if (i === middleware.length) fn = nextif (!fn) return Promise.resolve()try {return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));} catch (err) {return Promise.reject(err)}}}
}
复制代码

二、Redux中间件源码分析

在Redux中需要引入中间件的话,需引入applyMiddleware函数并将其作为参数传给createStore。下方enhancer就是就是applyMiddleware的返回值。

export default function createStore(reducer, preloadedState, enhancer) {...return enhancer(createStore)(reducer, preloadedState)
}
复制代码

applyMiddleware接受一个中间件数组为参数。

export default function applyMiddleware(...middlewares) {return createStore => (...args) => {const store = createStore(...args)let dispatch = () => {throw new Error(`Dispatching while constructing your middleware is not allowed. ` +`Other middleware would not be applied to this dispatch.`)}const middlewareAPI = {getState: store.getState,dispatch: (...args) => dispatch(...args)}const chain = middlewares.map(middleware => middleware(middlewareAPI))dispatch = compose(...chain)(store.dispatch)return {...store,dispatch}}
}
复制代码

其中compose用Array.prototype.reduce将中间件数组封装成一个层层包裹的函数。

function compose(...funcs) {return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
复制代码

若本来的中间件数组是

[a, b, c]

经过compose函数封装后,就成了

(...arg) => a(b(c(...arg)))

    dispatch = compose(...chain)(store.dispatch)
复制代码

经过这个过程后,每次调用dispatch就会在中间件中进行遍历。每个中间件都需要调用next(action)来保证中间件链都能被执行。

Redux中中间件的写法一般为

    const middleware = store => next => action => {...}
复制代码

根据上面的分析,store参数就是middlewareAPI,但是其中的dispatch并不是真正的dispatch,这是为了防止在中间件中调用store.dispatch而导致重新遍历整个中间件链。next是下一个中间件,需要传递action,直到最后一个中间件时,next即是原始的store.dispatch。

三、Koa2和Redux中间件比较

在两者中都出现了compose函数。
Koa2中的compose函数实现原理是用dispatch函数自身迭代,是从左向右执行中间件函数。而Redux中的compose实现原理是用了数组的reduce方法,从右向左执行中间件函数。两者执行顺序虽然不同,一样的是先执行的中间件可以获取后执行的中间件的状态(store的状态或者context的状态),实现了面向切面编程。

转载于:https://juejin.im/post/5b94b86c5188255c6a041c39

相关文章:

matlab内存管理(二)

转自&#xff1a;http://hi.baidu.com/bi%CB%AB%C9%FA%BB%A8/blog/item/5ab86c38ac2f45e715cecbab.html 1&#xff0c;确保内存的连续性Matlab 中数组必须占用连续分配的内存段当无法为新建的数组分配连续的内存段的时候Out of Memory 就会出现由于反复分配和释放数组会使可用的…

校招经验分享—高考结束!校招还会远么~~

作者 | 石晓文来源 | 转载自小小挖掘机&#xff08;ID: wAIsjwj&#xff09;今天是6.11&#xff0c;高考已经结束了&#xff0c;那大考-校招还会远么&#xff1f;我们先来看一下去年的校招时间表&#xff1a;互联网大厂校招一般7月就开始了&#xff0c;也就是说&#xff01;如果…

数据科学究竟是什么?

数据科学是一门将数据变得有用的学科。它包含三个重要概念&#xff1a; 统计机器学习数据挖掘/分析数据科学的定义 如果你回顾一下数据科学这个术语的[早期历史]()&#xff0c;会发现有两个主题密切相连&#xff1a; 大数据意味着计算机的使用频率增加。统计学家很难将纸张上所…

SQL with NUll处理,Join系列,between,in对比exists以及少量题目

2019独角兽企业重金招聘Python工程师标准>>> 1.一些题目: 选择在每一组B值相同的数据中对应的a最大的记录的所有信息,(用于论坛每月排行榜) Selecta,b,c from tableta wherea(select max(a) from tabletb where tableb.b tableta.b ) 随机抽取出10条数据 Select to…

清华大学提出APDrawingGAN,人脸照片秒变艺术肖像画

作者 | 刘永进教授来源 | 转载自数据派THU&#xff08;ID:DatapiTHU&#xff09;清华大学提出APDrawingGAN&#xff0c;该项工作被CVPR 2019录取为oral paper。CVPR是计算机视觉和人工智能领域内的国际顶级会议&#xff0c;2019共收到投稿5160篇&#xff0c;录取1300篇&#xf…

图像处理和图像识别中常用的OpenCV函数

1. cvLoadImage&#xff1a;将图像文件加载至内存&#xff1b; 2. cvNamedWindow&#xff1a;在屏幕上创建一个窗口&#xff1b; 3. cvDestroyWindow&#xff1a;销毁显示图像文件的窗口&#xff1b; 4. cvDestroyAllWindows&#xff1a;销毁显示图像文件的所有窗口…

SQLServer之DEFAULT约束

原文:SQLServer之DEFAULT约束DEFAULT约束添加规则 1、若在表中定义了默认值约束&#xff0c;用户在插入新的数据行时&#xff0c;如果该行没有指定数据&#xff0c;那么系统将默认值赋给该列&#xff0c;如果我们不设置默认值&#xff0c;系统默认为NULL。 2、如果“默认值”字…

tmux/screen里面如何用鼠标滚轮来卷动窗口内容

tmux里面用鼠标滚轮来卷动窗口内容在 tmux里面&#xff0c;因为每个窗口(tmux window)的历史内容已经被tmux接管了&#xff0c;所以原来console/terminal提供的ShiftPgUp/PgDn所显示的内容并不是当前窗口的历史内容&#xff0c;所以要用C-b [ 进入copy-mode&#xff0c;然后才能…

图像空间变换--imtransform

转自&#xff1a;http://juyishaanxi.blog.163.com/blog/static/602733002010522105439617/(非原处)空间几何变换将(w,z)坐标系上的图像变换为(x,y)坐标系上的图像&#xff0c;可以表示为&#xff1a; (x,y) T{(w,z) 比如&#xff1a; (x,y) T{(w,z)} (w/2, z/2) 仿射变…

谷歌用1.2万个模型“推翻”现有无监督研究成果!斩获ICML 2019最佳论文

作者 | 夕颜、Just出品 | AI科技大本营(ID:rgznai100)6 月 11 日&#xff0c;在美国加州长滩举行的 ICML 公布了 2019 年最佳论文奖&#xff0c;来自苏黎世联邦理工大学、谷歌大脑等的团队和英国剑桥大学团队摘得最佳论文奖项&#xff0c;此外&#xff0c;大会还公布了 7 篇获最…

实战:掌握PyTorch图片分类的简明教程 | 附完整代码

作者 | 小宋是呢转载自CSDN博客1.引文深度学习的比赛中&#xff0c;图片分类是很常见的比赛&#xff0c;同时也是很难取得特别高名次的比赛&#xff0c;因为图片分类已经被大家研究的很透彻&#xff0c;一些开源的网络很容易取得高分。如果大家还掌握不了使用开源的网络进行训练…

python group()

正则表达式中&#xff0c;group&#xff08;&#xff09;用来提出分组截获的字符串&#xff0c;&#xff08;&#xff09;用来分组 import re a "123abc456" print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) #123abc456,返回整体 print re.sea…

图像配准的方法

转自&#xff1a;http://blog.sina.com.cn/s/blog_4b9b714a0100d5k5.html 图像配准的方法 1 基于特征的图像配准 基于特征的图像配准首先提取图像信息的特征&#xff0c;然后以这些特征为模型进行配准。特征提取的结果是一含有特征的表和对图像的描述&#xff0c;每个特征由…

微软发布Visual Studio 2017 15.8

2019独角兽企业重金招聘Python工程师标准>>> 对于C#/VB/C项目&#xff0c;在Git分支检出和分支切换操作后不再需要重新加载解决方案&#xff0c;这加快了操作的完成。15.8支持新推出的F# 4.5&#xff0c;这无疑将会受到F#开发人员的欢迎。此外&#xff0c;用于F#项目…

推荐系统产品与算法概述 | 深度

作者丨gongyouliu转载自大数据与人工智能&#xff08;ID:gh_b8b5b02c348b&#xff09;作者在《推荐系统的工程实现》&#xff08;点击蓝字可回顾&#xff09;这篇文章的第五部分“推荐系统范式”中讲到工业级推荐系统有非个性化范式、完全个性化范式、群组个性化范式、标的物关…

【iOS-cocos2d-X 游戏开发之十六】Cocos2dx编译后的Android自动使用(-hd)高清图设置自适应屏幕...

本篇主要介绍Cocos2dx项目开发过程中或者说项目务必遇到的一些知识点&#xff08;ps.貌似Himi博客写的都是务必的 :tx: Himi认为写别人没写的才更容易吸引人不是&#xff5e;&#xff09; OK&#xff0c;不多说废话&#xff0c;第一个介绍的是修改项目配置让你的Android项目支…

matlab图像处理命令(一)

转自&#xff1a;http://blog.csdn.net/langyuewu/archive/2009/05/02/4144120.aspx(非原处) 1.applylut 功能: 在二进制图像中利用lookup表进行边沿操作. 语法: A applylut(BW,lut) 举例 lut makelut(sum(x(:)) 4,2); BW1 imread(text.tif); BW2 applylut(BW1,lut); imsh…

MYSQL 查询数据排序数据和分组数据

在mysql查询过程中&#xff0c;可以对数据进行过滤&#xff0c;也可以对数据进行排序&#xff0c;可以对数据分组&#xff0c;下面分别讲述排序数据和分组数据例子。1&#xff0c;数据的排序 使用 ORDER BYselect * from where id10 order by id (正序&#xff0c;倒序)正序 AS…

Oracle RAC系列之:利用srvctl管理RAC数据库

srvctl即Server Control&#xff0c;是Oracle提供的一个命令行工具&#xff0c;用以用于管理Oracle的RAC环境。srvctl在Oracle 9i中被引入&#xff0c;Oracle10g、11g对其功能进行了很大的增强和改进。下面介绍下此命令的简单用法。 一、 查看实例状态&#xff08;srvctl statu…

matlab图像处理命令(二)

转自&#xff1a;http://blog.163.com/crazyzcs126/blog/static/1297420502010229104452729/ (非原处) 图像增强 1. 直方图均衡化的 Matlab 实现 1.1 imhist 函数 功能&#xff1a;计算和显示图像的色彩直方图 格式&#xff1a;imhist(I,n) imhist(X,map) 说明&#x…

10万人的1000万张图像,微软悄然删除最大公开人脸数据集

作者 | 神经小姐姐转载自HyperAI超神经&#xff08;ID&#xff1a;HyperAI&#xff09;前几日&#xff0c;微软静悄悄地删除了一个公开的名人图片数据集。这个本为世界上最大的公开人脸识别数据集&#xff0c;现在已经不能通过微软的渠道访问。这个数据集包含了 10 万张名人面部…

密码学原理学习笔记

攻击的类型: 唯密文攻击(COA)&#xff1a;攻击者只知道密文 已知明文攻击(KPA)&#xff1a;攻击者知道同一密钥下密文对应的明文。 选择明文攻击(CPA)&#xff1a;攻击者可以事先任意选择一定数量的明文&#xff0c;让被攻击的加密算法加密&#xff0c;并得到相应的密文。 选择…

终于申请博客了

今天终于下定决心在51CTO博客安家了。以后要坚持不断的写博客。以此来督促自己不断的学习和总结。把自己所掌握的技术和过往经验总结出来。转载于:https://blog.51cto.com/weijishui/971044

一种二维条码图像处理流程

目前&#xff0c;二维条码主要分两类&#xff1a; (1)、堆叠式二维条码&#xff1a;PDF417、Code 49&#xff1b; (2)、矩阵式二维条码&#xff1a;QR Code、Maxicode、Data Matrix。 本条码类似于Maxicode&#xff0c;处理过程大致为&#xff1a; (1)、图像灰度化&#xff…

vue中 静态文件引用注意事项

&#xff08;一&#xff09;assets文件夹与static文件夹的区别区别一&#xff1a;assets文件是src下的&#xff0c;所以最后运行时需要进行打包&#xff0c;而static文件不需要打包就直接放在最终的文件中了区别二&#xff1a;assets中的文件在vue中的template/style下用../这种…

百度AI快车道—企业深度学习实战营,推荐系统主题专场即将开课

身处信息过载的时代&#xff0c;在各大门户网站上&#xff0c;每天会有十万左右的新闻报道产出&#xff0c;京东淘宝等购物平台每小时就有上百万的商品上架出售&#xff0c;在B站、优酷、爱奇艺、搜狐等视频网站上每秒就有几百个小时的视频上线。所有人都正在经历一场信息变革。…

SIFT特征提取算法总结

转自&#xff1a;http://www.jellon.cn/index.php/archives/374 一、综述 Scale-invariant feature transform(简称SIFT)是一种图像特征提取与匹配算法。SIFT算法由David.G.Lowe于1999年提出&#xff0c;2004年完善总结&#xff0c;后来Y.Ke(2004)将其描述子部分用PCA代替直方…

一步步构建大型网站架构

之前我简单向大家介绍了各个知名大型网站的架构&#xff0c;MySpace的五个里程碑、Flickr的架构、YouTube的架构、PlentyOfFish的架构、WikiPedia的架构。这几个都很典型&#xff0c;我们可以从中获取很多有关网站架构方面的知识&#xff0c;看了之后你会发现你原来的想法很可能…

商汤科技举办病理、放疗两大MICCAI国际挑战赛,推动AI医疗落地

近日&#xff0c;商汤科技宣布将联合衡道病理、上海交通大学医学院附属瑞金医院、西京医院、上海市松江区中心医院举办MICCAI 2019消化道病理图像检测与分割国际挑战赛&#xff0c;联合医诺智能科技、浙江省肿瘤医院举办MICCAI 2019放疗规划自动结构勾画国际挑战赛&#xff0c;…

vue实战(1)——解决element-ui中upload组件使用多个时无法绑定对应的元素

解决element-ui中upload组件使用多个时无法绑定对应的元素 以前写的项目关于图片上传的都是单张或几张图片上传&#xff08;主要是基于vue的element&#xff09;&#xff0c;图片路径都是固定写的&#xff0c;所以遇见过列表中多个上传图片的问题&#xff0c;先看下常用的形式 …