generator探幽(1)--koa中间件机制浅析

本系列旨在经由历程对co,koa等库源码的研讨,进而明白generator在异步编程中的严重作用(ps:一切代码请在node –harmony或许iojs环境中运转)

koa中间件的情势

置信用过koa的小伙伴肯定很熟习下面这段代码

var app = require('koa')(),
    router = require('koa-router')();

app.use(function *(next){
    console.log(1);
    yield next;
    console.log(5);
});
app.use(function *(next){
    console.log(2);
    yield next;
    console.log(4);
});
app.use(function *(){
    console.log(3);
});

app.listen(3000);

当一个要求抵达的时刻,控制台会顺次输出1 2 3 4 5,这就是koa中壮大的middleware特征,撇开koa自身,我们来扯扯middleware这东西是怎样完成的

yield *iterator

不熟习generatoriterator的小伙伴能够先看下阮一峰教师编写的《ES6入门》的generator函数这一节
假定你已熟习了generator和iterator,如今我们来看一段代码

function *m1(){
    console.log(1);
    yield *m2Iterator;
    console.log(3);
}

function *m2(){
    console.log(2);
}
var m1Iterator = m1(),
    m2Iterator = m2();

m1Iterator.next();//

上面代码运转后,控制台会顺次输出1 2 3,这是因为在m1函数内部,yield背面跟的是一个iterator
m1Iterator.next()挪用后,m1函数最先实行。
m1运转到yield *m2Iterator时,不会停息,而是直接跳进m2函数实行m2函数内的代码。
因为m2函数中没有yield,因而会一向实行完m2函数中的代码,并返回至m1函数中实行yield *m2Iterator背面的代码。

middleware中间件的雏形

明白了上面的历程后,我们接着看下面这段代码

function *m1(){
    console.log(1);
    yield *m2();
    console.log(5);
}

function *m2(){
    console.log(2);
    yield *m3();
    console.log(4);
}

function *m3(){
    console.log(3);
}

m1().next(); //控制台顺次输出1 2 3 4 5

是否是情势跟我们一最先看到的koa的中间件有点接近了?

compose

composekoa里用来完成中间件机制的模块
compose函数最症结的一段代码

while(i--){
    next = middleware[i].call(this, next);
}
yield *next;

这段代码把middleware中传进来的generator数组逆序掏出并顺次实行,每次实行的时刻把上次generator实行返回的iterator看成参数传进去,一切generator实行完今后,挪用第一个iterator
因而,在generator中间件函数中,实在yield背面跟的是个iterator,即yield *next
下面用一个例子来申明这个历程

function *m1(next){
    console.log(1);
    yield *next;
    console.log(5);
}

function *m2(next){
    console.log(2);
    yield *next;
    console.log(4);
}

function *m3(){
    console.log(3);
}

var gen = compose([m1, m2, m3]),
    it = gen();
//compose([m1, m2, m3])()能够设想成它做了这么一些事(伪代码):
//1 var it3 = m3();
//2 var it2 = m2(it3);
//3 var it1 = m1(it2);
//4 gen = function(){
//          yield *it1;  
//        }

it.next(); //控制台顺次输出1 2 3 4 5

如今就很像koa的中间件的写法了。唯一的差别是koa中运用的是yeild next而我们这里用的是yield *next
实在在koayeild nextyeild *next结果是等价的,这重要得益于co库,我们今后再来好好扯扯这小玩意~

    原文作者:zank
    原文地址: https://segmentfault.com/a/1190000002738448
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞