generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次。
generator和函数不同的是,generator由function*
定义(注意多出的*号),并且,除了return
语句,还可以用yield
返回多次:
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
编写一个产生斐波那契数列的函数,可以这么写:
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 1;
while (n < max) {
yield a;
t = a + b;
a = b;
b = t;
n ++;
}
return a;
}
调用generator对象有两个方法,一是不断地调用generator对象的next()
方法:
var f = fib(5); // fib {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window},fib(5)仅仅是创建了一个generator对象,还没有去执行它
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: true}
第二个方法是直接用for ... of
循环迭代generator对象,这种方式不需要我们自己判断done
:
for (var x of fib(5)) {
console.log(x); // 依次输出0, 1, 1, 2, 注意,没有3
}
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
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);
}