generator是ES6中非常强悍的一个新特性。
用generator 实现斐波那契数列,如下:
function* fifo (){
let a = 0;
let b = 1;
yield a;
yield b;
while(true){
let next = a+b;
a = b;
b = next;
yield next;
}
}
let generator = fifo();
for ( let i = 0 ; i < 10; i++ ){
console.log( generator.next().value)
}
用这个例子学习一下generator。
# 定义一个generator
generator函数与普通函数的语法区别在于,在function语句之后和函数名之前,有一个“ *
”作为generator函数的标识符。
function* fifo(){
//...
}
也可以使用表达式定义
const fifo = function*(){
//...
}
# yield语句
yield
语句的作用和return
语句有些相似,但并非退出函数体,而是切出当前函数的运行时,同时可以将一个值带到主线程中。
即yield
语句可返回多次。
# 启动generator
generator函数不能直接作为普通的函数使用,因为在调用时无法直接执行其中的逻辑代码。执行generator函数会返回一个generator对象,用于运行generator内容和接受其中的值。
let generator = fifo();
# generator VS普通函数
generator还有另一个巨大的好处,就是把异步回调代码变成“同步”代码
没有generator之前的黑暗时代,用AJAX时需要这么写代码:
ajax('http://url-1', data1, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-2', data2, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-3', data3, function (err, result) {
if (err) {
return handle(err);
}
return success(result);
});
});
});
回调越多,代码越难看。
有了generator的美好时代,用AJAX时可以这么写:
try {
r1 = yield ajax('http://url-1', data1);
r2 = yield ajax('http://url-2', data2);
r3 = yield ajax('http://url-3', data3);
success(r3);
}
catch (err) {
handle(err);
}
看上去是同步的代码,实际执行是异步的。