美文网首页
Generator的使用原理源码

Generator的使用原理源码

作者: vivianXIa | 来源:发表于2021-04-13 14:33 被阅读0次

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

    相关文章

      网友评论

          本文标题:Generator的使用原理源码

          本文链接:https://www.haomeiwen.com/subject/kuaqlltx.html