generator 每当生成器函数产生一个新值后,它的执行状态会被保留,直到下次请求到来,它就会从上次离开的位置恢复执行。
基本的使用
function* read() { // 生成器 他执行的结果叫迭代器
var a = yield 1;
console.log('过程a',a);
var b = yield 2;
console.log('过程b',b);
var c = yield 3;
console.log('过程c',c);
}
let it = read();
let a = it.next();
console.log("一次结果a",a);
let c = it.next("zzz");
console.log("二次结果c",c);
- 第一次调用next(), 并没有输出a,说明执行到yield 1;
- 第二次调用,输出了过程a,并且a的值,就是第二次传入的值‘zzz’
-
每次执行后返回的结果是{value,done},也就是yield后边内容执行的结果和done标志是否结束的标志,执行到最后会返回true
调用2次next
generate源码研究
可以去babel转一下generate方法,其中_context.next 2,6,10是自己生成的 我们可以不用管它了
babel直接转generate
var _marked = /*#__PURE__*/regeneratorRuntime.mark(read);
function read() {
var a, b, c;
return regeneratorRuntime.wrap(function read$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return 1;
case 2:
a = _context.sent;
console.log(a);
_context.next = 6;
return 2;
case 6:
b = _context.sent;
console.log(b);
_context.next = 10;
return 3;
case 10:
c = _context.sent;
console.log(c);
case 12:
case "end":
return _context.stop();
}
}
}, _marked);
}
可以看到regeneratorRuntime里边有一个mark和wrap方法,wrap方法返回next()方法,并且可以执行传入的迭代函数iteratorFn。可以还原出对应的wrap方法
let regeneratorRuntime = {
mark(genFn){
return genFn
},
wrap(iteratorFn){
const context = {
next:0,
done:false, // 表示迭代器没有完成
stop(){
this.done = true
}
}
let it ={ };
it.next = function (v) { // 用户调用的next方法
context.sent = v
let value = iteratorFn(context);
return {
value,
done:context.done // 是否完成
}
}
return it;
}
}
网友评论