Generator

调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着valuedone两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

  • 关键字 yield next

    1. function * fn(){
    2. yield 'hello';
    3. yield 'world';
    4. return 'end'
    5. }
    6. let f = fn()
    7. console.log(f.next())
    8. console.log(f.next())
    9. console.log(f.next())
    10. console.log(f.next())
    11. //{ value: 'hello', done: false }
    12. //{ value: 'world', done: false }
    13. //{ value: 'end', done: true }
    14. //{ value: undefined, done: true }

    yield 表达式

    由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
    遍历器对象的next方法的运行逻辑如下。
    (1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
    (2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
    (3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
    (4)如果该函数没有return语句,则返回的对象的value属性值为undefined

  • 延迟函数执行

    1. function* s() {
    2. console.log('执行了!')
    3. }
    4. var generator = s();
    5. setTimeout(function () {
    6. generator.next()
    7. }, 2000);

    Symbol.iterator

    为每一个对象定义了默认的迭代器。该迭代器可以被 [for...of](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of) 循环使用。

    1. var myIterable = {}
    2. myIterable[Symbol.iterator] = function* () {
    3. yield 1;
    4. yield 2;
    5. yield 3;
    6. };
    7. [...myIterable] // [1, 2, 3]

    Generator.prototype.throw()

    Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获。 ```javascript var g = function* () { try { yield; } catch (e) { console.log(‘内部捕获’, e); } };

var i = g(); i.next();

try { i.throw(‘a’); i.throw(‘b’); } catch (e) { console.log(‘外部捕获’, e); } // 内部捕获 a // 外部捕获 b

  1. <a name="KNPuG"></a>
  2. ### Generator.prototype.return()
  3. Generator 函数返回的遍历器对象,还有一个`return`方法,可以返回给定的值,并且终结遍历 Generator 函数。
  4. ```javascript
  5. function* gen() {
  6. yield 1;
  7. yield 2;
  8. yield 3;
  9. }
  10. var g = gen();
  11. g.next() // { value: 1, done: false }
  12. g.return('foo') // { value: "foo", done: true }
  13. g.next() // { value: undefined, done: true }

yield* 表达式

如果在 Generator 函数内部,调用另一个 Generator 函数。需要在前者的函数体内部,自己手动完成遍历。

异步应用

  • 封装
    1. function * $http(){
    2. yield fetch('...')
    3. }
    4. const http = $http()
    5. http.next.value.then((d)=>d.json).then(d=>http.next(d))