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 函数。
```javascript
function* 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))