with廖老师前端记录
https://www.liaoxuefeng.com/wiki/1022910821149312/1023024381818112
generator
- generator(生成器)是ES6标准引入的新的数据类型。一个generator看上去像一个函数,但可以返回多次。
定义
- generator和函数不同的是,generator由
function*
定义(注意多出的*
号), - 除了
return
语句,还可以用yield
返回多次。
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
var gen = foo(10);
gen.next().value; // 11
gen.next(); // {value: 12, done: false}
gen.next(); // {value: 13, done: true}
gen.next(); // {value: undefined, done: true}
- 直接调用一个generator和调用函数不一样,
gen(10)
仅仅是创建了一个generator对象,还没有去执行它
next
调用generator对象有两个方法,一是不断地调用generator对象的next()
方法
-
每次遇到
yield x;
就返回一个对象{value: x, done: true/false}
,然后“暂停”。 -
返回的
value
就是yield
的返回值,done
表示这个generator是否已经执行结束了。 -
如果
done
为true
,则value
就是return
的返回值。
第二个方法是直接用for ... of
循环迭代generator对象,这种方式不需要自己判断done
- 不包含return:return;一般为
for (var x of gen(10)) {
console.log(x); // 依次输出11,12
}
解决回调地狱
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);
}
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);
}
看上去是同步的代码,实际执行是异步的。
因为generator可以在执行过程中多次返回,所以它看上去就像一个可以记住执行状态的函数
自增ID
// 要生成一个自增的ID,可以编写一个next_id()函数(每次保存状态):
function* nextId() {
var id = 0;
while(true) {
// yield可以用来加强控制,懒汉式加载
yield ++id;
}
}