个人还是很喜欢这种机制,也想搞一个这般的 Workflow 辅助类出来,不过不想用 Generator,所以折腾了一小下……
不得不说的 yield *
yield*
最大的作用,就是将Generator
嵌在另一个Generator
的内部执行。
|
|
执行结果是13
,是的,2不会被输出,但是如果换成:
|
|
就等同于:
输出就是123
就好了。
而这也是koa2的中间件核心实现机制,笑话一下自己最开始搞出来的遍历行为,傻在next
上了,囧~~
async/await模式的实现
如果还不明白,那么就看这个:
|
|
循环内嵌之后,你只需要遍历a的Iterator就行了,会展开嵌入后面所有的Generator
!!
所以核心问题就变成了,如何定义出所需要的方法a而已。
koa的middlewares
是一个数组,为了能够得到要访问的方法,其实就是middlewares[0]的封装。我们知道每个async function
其实就是一个Generator function
,那么我只需要把参数next
指向下一个中间件函数,并且确保调用时使用yield*
去调用,并且参数绑定ctx和下一个next。
所以我需要的可能是这样的:
|
|
再换一下,用async/await:
|
|
发现规律了么……
nexta调用的是函数a,将nextb作为next参数传入,而nextb调用b,将nextc作为参数传入,同理继续。最后一个指向空就行了,啥也不干。
那么:
|
|
貌似大功告成?还得继续……
中间件是需要传入数据的,简单理解为:一个数据要从第一个中间件进入,最终从第一个中间件的after出来,核心目的是改变这个数据,因此在当前的模式下,最好不要传值,我们来看:
|
|
根据上面的调用模式,如果一直是值引用,那么就要 return 处理后的值,与代码中的await next()
不符了,而且使用还会变得麻烦,所以koa选择使用context的概念,传入一个Object
的引用,然后一直去修改它。
那么我们接下来要做的事情,其实就是支持 ctx 参数了:
|
|
能不能更简便些呢?
好吧,反正我还是没看明白 koa 的 compose 结果,怎么被使用的,直接传一个 ctx 作为参数就达到效果了。
我其实怀疑是 koa-convert 搞的鬼,默认都是 Generator,都被转换成 async 了,然后 call 了ctx 和 next。
应该是这样吧……