Generator
调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
关键字 yield next
function * fn(){yield 'hello';yield 'world';return 'end'}let f = fn()console.log(f.next())console.log(f.next())console.log(f.next())console.log(f.next())//{ value: 'hello', done: false }//{ value: 'world', done: false }//{ value: 'end', done: true }//{ 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。延迟函数执行
function* s() {console.log('执行了!')}var generator = s();setTimeout(function () {generator.next()}, 2000);
Symbol.iterator
为每一个对象定义了默认的迭代器。该迭代器可以被
[for...of](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of)循环使用。var myIterable = {}myIterable[Symbol.iterator] = function* () {yield 1;yield 2;yield 3;};[...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
<a name="KNPuG"></a>### Generator.prototype.return()Generator 函数返回的遍历器对象,还有一个`return`方法,可以返回给定的值,并且终结遍历 Generator 函数。```javascriptfunction* gen() {yield 1;yield 2;yield 3;}var g = gen();g.next() // { value: 1, done: false }g.return('foo') // { value: "foo", done: true }g.next() // { value: undefined, done: true }
yield* 表达式
如果在 Generator 函数内部,调用另一个 Generator 函数。需要在前者的函数体内部,自己手动完成遍历。
异步应用
- 封装
function * $http(){yield fetch('...')}const http = $http()http.next.value.then((d)=>d.json).then(d=>http.next(d))
