• ECMAScript6 入门 Generator


    ----------------------------------------------------------------------------------------------------------------------------
    
    基本概念
    Generator 函数是一个状态机,封装了多个内部状态,执行 Generator 函数会返回一个遍历器对象
    Generator 函数除了状态机,还是一个遍历器对象生成函数,
    返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态
    
    function* helloWorldGenerator() {
      yield 'hello';
      yield 'world';
      return 'ending';
    }
    
    var hw = helloWorldGenerator();
    该函数存在三个状态了
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    调用 Generator 函数后,该函数并不执行
    返回的也不是函数运行结果,而是一个指向内部状态的指针对象(遍历器对象)
    
    下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态
    返回的对象是yield表达式的值以及遍历是否完成
    (遇到下一个yield或者return为止)
    hw.next()
    // { value: 'hello', done: false }
    
    hw.next()
    // { value: 'world', done: false }
    
    hw.next()
    // { value: 'ending', done: true }
    
    hw.next()
    // { value: undefined, done: true }
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    yield 表达式
    遍历器对象的next方法的运行逻辑如下
    (1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
    (2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
    (3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,
    并将return语句后面的表达式的值,作为返回的对象的value属性值。
    (4)如果该函数没有return语句,则返回的对象的value属性值为undefined。
    注意:yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行(如果没有执行到这一步,就永远都不会执行该表达式)
    (因此相等于手动提供了一个“惰性求值”的语法功能)
    (5)yield不能进行嵌套操作,并且yield必须在定义的function*()函数里面,在数组等其他的回调函数是不起作用
    //(6) yiled 后面使用的返回必须是返回了一个Promise对象
    
    重点:bluebirdjs 类库会将普通函数转化成返回Promise对象的函数
    
    ----------------------------------------------------------------------------------------------------------------------------
    next() 方法的参数
    1:该参数会被当成上一个yield表达式的返回值
    ----------------------------------------------------------------------------------------------------------------------------
    
    for...of 循环
    for...of循环可以自动遍历 Generator 函数时生成的Iterator对象,且此时不再需要调用next方法
    1:一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,就是不包含最后的那个return
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    Generator.prototype.throw()
    Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    Generator.prototype.return()
    Generator 函数返回的遍历器对象,还有一个return方法,可以返回给定的值,并且终结遍历 Generator 函数
    注释:return与next的简单区别
    1:console.log(g.return('foo')); // { value: "foo", done: true } 终结了所以是true,并且返回了指定的值
    2:return没有参数的时候,返回{ value: undefined, done: true }
    3:next没有参数的时候返回本次yield语句的返回值
    4:return有参数的时候,覆盖本次yield语句的返回值,也就是说,返回{ value: 参数, done: true };
    next有参数的时候,覆盖上次yield语句的返回值
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    next()、throw()、return() 的共同点
    next()、throw()、return()这三个方法本质上是同一件事,可以放在一起理解。它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    yield* 表达式
    如果在 Generator 函数内部,调用另一个 Generator 函数,默认情况下是没有效果的
    单纯的使用另一个Generator无效
    yield* fn() 这样才会起效果
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    作为对象属性的 Generator 函数
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    Generator 函数的this
    
    ----------------------------------------------------------------------------------------------------------------------------
    
    Generator 与状态机
    1:常用的状态机写法
    var ticking = true;
    var clock = function() {
      if (ticking)
        console.log('Tick!');
      else
        console.log('Tock!');
      ticking = !ticking;
    }
    上面代码的clock函数一共有两种状态(Tick和Tock),每运行一次,就改变一次状态:
    
    2:Generator的写法
    var clock = function*() {
      while (true) {
        console.log('Tick!');
        yield;
        console.log('Tock!');
        yield;
      }
    };
    
    ----------------------------------------------------------------------------------------------------------------------------
    Generator 函数的异步应用
    
    已知的异步编程
    {
        回调函数
        事件监听
        发布/订阅
        Promise对象
    }
    
    回调函数写法
    fs.readFile('/etc/passwd', 'utf-8', function (err, data) {
      if (err) throw err;
      console.log(data);
    });
    
    Promise写法
    var readFile = require('fs-readfile-promise');
    
    readFile(fileA)
    .then(function (data) {
      console.log(data.toString());
    })
    .then(function () {
      return readFile(fileB);
    })
    .then(function (data) {
      console.log(data.toString());
    })
    .catch(function (err) {
      console.log(err);
    });
    
    Generator写法
    function* gen(x) {
      var y = yield x + 2;
      return y;
    }
    
    var g = gen(1);
    g.next() // { value: 3, done: false }
    g.next() // { value: undefined, done: true }
    
    数据交换与错误解决
    {
        next返回值的value属性,是Generator函数向外输出,next函数还可以接受参数向函数体输入数据
        Generator函数体内部还可以部署错误处理代码,捕获函数体外抛出的错误
        
    }
    
    参数的求值策略
    {
        传值调用:在进入函数体之前进行调用
        传名调用:将表达式传入函数体,在执行的时候才调用
    }
    
    Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数
    
    Generator函数的自动执行方法
    {
        
        
        
    }
    不忘初心,不负梦想
  • 相关阅读:
    面试题系列--【vue的生命周期】
    面试题系列--【hash和history的区别】
    ES6系列--【事件循环 EventLoop(Promise,setTimeOut,async/await执行顺序)】
    ES6系列--【ES6数组新增方法】
    ES6系列--【ES6 新增字符串方法】
    微信小程序系列--【VXML语法、VMSS样式、条件渲染、列表渲染、模板、引用、组件、事件系统】
    微信小程序系列--【小程序注册、工程创建、全局配置、页面配置】
    微信小程序系列---【五星好评案例】
    react系列---【Hooks】
    2019.9.18-单向循环链表删除元素(+之前完整代码)
  • 原文地址:https://www.cnblogs.com/panrui1994/p/11597685.html
Copyright © 2020-2023  润新知