如何理解 koa 中间件执行机制

前几天研究了TJ的koa/co4.x和一系列koa依赖的源码,在知乎上作出了人生首次回答(并且我真得不再想去知乎回答技术问题了_(:з」∠)_),所以把文字搬到这里。前端

ES2015 Generator/Yield

关于Generator/Yield 这几篇文章已经写得足够清晰了:node

Koa的运行机制

简单地画了一张图解释koa的处理流程:python

图片描述

在koa里定义的middleware均为generator function(包括内置在顶端的respond),这是为了能从任意middleware中容易地切换到其它middleware里(若是你是前端程序员,能够理解为浏览器捕获事件的capture和propagation过程,若是你是python程序员,能够理解为jungle的middleware机制,若是你是Java程序员,这种方式则是典型的切面编程)。git

为了实现这种横穿多个middleware的特性,koa经过把后一个generator做为参数(koa里经常使用next)传入前一个generator实现(#见koa-compose源码,这也是为何前两个middleware有next参数而最后一个没有)。程序员

能够看到,在koa中yield的使用是在co,而co则是包装了generator/yield & Promise以模拟async/await,提供了一个更高层次的异步语法抽象。es6

koa在加载且合并全部的middleware以后,传递给co执行(确切地说是在http.createServer的callback触发后执行),co以图中所示逻辑不断拆解generator function,执行yield右侧固定的几种表达式(Array,Object,generator function,Promise,thunkify function),这5种表达式最终都会转化为Promise,以达处处理异步函数的目的。github

co内部封装了onFulfilled和onRejected函数,当yield右侧的promise resolve以后,则会调用onFullfield函数,其包含了一条关键语句gen.next(res)#这句代码 用以给yield表达式赋值并执行下一次迭代。编程

koa经过上文的方式「深刻」->「浅出」,最终在顶层的respond middleware里send response。promise

注:#thunk是co先前版本处理异步函数的方式,经过thunk能够将异步函数封装成curry,传入普通参数后造成仅须要callback参数的偏函数,以此简化callback调用代码(目前co中的thunk偏函数已经被#无情地Promise化了)。浏览器

by Abruzzi's blog

相关文章
相关标签/搜索