0
点赞
收藏
分享

微信扫一扫

Generator的使用原理源码

思考的鸿毛 2021-09-30 阅读 63
JavaScript

基本的使用

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


generate源码研究

可以去babel转一下generate方法,其中_context.next 2,6,10是自己生成的 我们可以不用管它了


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;
    }
}
举报

相关推荐

0 条评论