Koa的执行过程
背景:JavaScript为了实现异步编程,传统的方式有回调函数、事件监听等。所谓回调函数,就是把任务的第二段单独写在一个函数里,等到任务再次执行的时候,就执行这个函数(其实所谓的异步编程,也就是将任务分段执行)。这种方式在多个回调函数嵌套的时候,会变得难以管理,出现所谓的回调地狱(callback hell),为了解决这个问题,出现了Promise。Promise提供了then()方法,加载回调函数,每次返回this,实现链式调用。后来,到了ES6又出现了Generator函数。它最大的特点就是可以暂停执行函数,在需要暂停的地方用yield语句注明。
使用Generator实现异步编程:
function* gen(x){
try{
let y = yield x + 2;
}catch(err){
console.log(err);
}
return y;
}
var g = gen(10);
g.next(); // 返回Object{value:12,done:false},
g.next();// 返回Object{value:undefined,done:true}
每次执行next()返回一个对象,其中value是yield语句后面的表达式的值,表示当前阶段的值。done表示任务是否执行完毕。
不同于express简单的利用中间件传递控制权,在Koa中,用户请求通过中间件,遇到yield next语句时,会暂停执行当前中间件的剩余代码,请求被传递到下一个符合要求的路由,并直到yield next 捕获不到下一个中间件时,逆序返回继续执行代码(downstream)。
这种执行方式被称为级联(Cascading)。有点像CSS代码的继承嵌套的结构。
middleware1{
//do something...
//yield next
middleware2{
//do something...
//yield next
middleware3{
//no next yield!
}
//do middleware2 left
}
//do middleware1 left
}
下图可以解释这一过程