世界上最伟大的投资就是投资自己的教育
![随风 · 练气](https://rails365.oss-cn-shenzhen.aliyuncs.com/uploads/user/avatar/1/e011f5d3876565d26f91684dfcf83303.png)
es6 的 generator 和 Node.js 的下一代框架 koa
1. generator
es6 有一个新功能特性,叫 generator,它是解决回调地狱的一个生成器。
众所周知,nodejs 的一大特性就是可以利用异步回调,它是优点,但也带来了回调噩梦。
有很多方法可以解决和减少回调嵌套太深的问题,比如 promise, async,但都解决得不太彻底。
generator 才是真正解决这类问题的利器,而本节所讲的 koa 框架也是基于 generator。
要写一个 generator 函数很简单,我们先来看一个简单的函数。
var hello = function(name) {
return 'hello ' + name;
}
console.log(hello('James'));
使用node --harmony example.js
执行这个脚本。
将输出:
hello James
要改写成 generator,很简单,只需要加一个*
,如下:
var hello = function *(name) {
return 'hello ' + name;
}
console.log(hello('James'));
终端将输出:
{}
现在还不行,再来改写一下。我们使用了next
关键字。
var hello = function *(name) {
return 'hello ' + name;
}
var gen = hello('James');
console.log(gen.next());
这个终端输出了我们要的效果:
{ value: 'hello James', done: true }
之前返回的是空对象{}
,现在有值了。
value
代表返回的值,done
代表这个 generator 是不是已经完成终止了。
什么意思?generator 还有状态?
有的,它可以被暂停,重新运行,可以终止。
我们来试下它是如何被暂停的,这个时候得用yield
关键字。
var hello = function *(name) {
yield 'my name is ' + name;
return 'hello ' + name;
}
var gen = hello('James');
console.log(gen.next());
终端输出:
{ value: 'my name is James', done: false }
done: false
表示还没真正终止,停在了yield
关键字所在的那一行。
要让它真正终止,得再调用一次next
命令。
var hello = function *(name) {
yield 'my name is ' + name;
return 'hello ' + name;
}
var gen = hello('James');
console.log(gen.next());
console.log(gen.next());
输出:
{ value: 'my name is James', done: false }
{ value: 'hello James', done: true }
要调用两次next
程序才最终停止。
下面给一个更直观的例子让你感受一下 generator。
// 代码来源于https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
function* idMaker(){
var index = 0;
while(index < 3)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined
说了这么多,你可能会觉得,这个有什么用啊,能解决异步回调的问题?
能的,它的神奇在于 yield 那个命令,你可以写很多行这样的命令,后面接的是异步任务。
比如:
function* gen(){
var result;
result = yield fetch('a');
console.log(result);
result = yield fetch('b');
console.log(result);
result = yield fetch('c');
console.log(result);
}
2. koa
next generation web framework for node.js
koa是下一代的 nodejs web 框架。以前比较流行的是 express 框架,现在好多人研究这个,express 的主要开发者现在都转向于 koa 的开发了。
本节所讲的 koa 是第一版本的,如果要使用第二版本的,只是语法变了,思想却是不变的
我们先来感受一下 koa。
先来安装。
$ npm install koa
创建 app.js 文件,内容如下:
var koa = require('koa');
var app = koa();
app.use(function *(){
this.body = 'Hello World';
});
app.listen(3000);
使用node app.js
运行这个文件,浏览器将输出Hello World
。
这个没什么,只是输出一行简单的文本。
我们再来看一个例子,是官方列出的。
// 代码来源于https://code.tutsplus.com/tutorials/introduction-to-generators-koajs-part-1--cms-21615
var koa = require('koa')();
koa.use(function* (next) {
//do something before yielding/passing to next generator function in line which will be 1st event in downstream
console.log("A");
yield next;
// do something when the execution returns upstream, this will be last event in upstream
console.log("B");
});
koa.use(function* (next) {
// do something before yielding/passing to the next generator function in line, this shall be 2nd event downstream
console.log("C");
yield next;
// do something when the execution returns upstream and this would be 2nd event upstream
console.log("D");
});
koa.use(function* () { // do something before yielding/passing to next generator function in line. Here it would be last function downstream
console.log("E");
this.body = "hey guys";
console.log("F"); // First event of upstream (from the last to first)
});
koa.listen(3000);
它将输出:
A
C
E
F
D
B
为什么会是这样呢,这跟 generator 有关。
要理解这个,先来理解一下 koa 的特性。
开发 koa,你会觉得你在写 middleware,这个东西有点像 ruby 的rack middleware
。
它的中文名可以译成中间件
。
ruby 的中间件是这样的,它传入一个环境变量 (env),经过中间件的处理,返回一个数组,数组内容是 [status, headers, body]。
分别是状态码,响应头信息,内容体。
一个中间件处理完之后,并不直接返回,而是把它的结果交给下一个中间件,直接全部处理结束,才返回。
它有点像一坐桥,连接桥头和桥尾两端,然后像 koa 应用是由很多这样的桥组成。
它是用中间件来组合而成一个应用。
koa.use
里面的就可以理解为一个中间件。
这样有什么好处呢?
好处多着呢,比如可以统一处理一些事情,比如 cache,日志输出,不然没有中间件,你要处理这样的东西,或许只能在应用中,一行行地改,而有了中间件,它在中间拦截处理了,很方便,特别有意思的是,koa 应用可以作为一个中间件应用包在一个 express 应用中,要开发 koa 的中间件也很简单,使用别人开发好的,一拿来就能用,超级方便。
现在回头来看上面那个代码,为什么是那样输出呢?
你得理解yield
这个指令,它会暂停你的中间件,会执行权交给下一个中间件,等下个中间件执行完,才会最终执行yield
之后的命令。所以最后输出的是B
。
koa 之路还很长,好好研究吧。
完结。
本站文章均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn
粤公网安备 44152102000088号
| 粤ICP备19038915号