ES6定义generator标准是借鉴了Python的generator的概念和语法。
一个generator看上去像一个函数,但可以返回多次。
Generator函数使用方法
- function和函数名之间有一个*号
- 函数体内部使用了yield表达式,例如:
function* gen(x) {
yield x+1;
yield x+2;
return x+3;
}
- 单纯运行generator函数后,只会返回一个generator对象并没有执行它。
调用generator对象有两个方法:
- 不断的调用generator对象的next()方法:
var f = gen(5);
f.next(); //{value: 6, done: false}
f.next(); //{value: 7, done: false}
f.next(); //{value: 8, done: true}
next()方法会执行generator的代码,然后,每次遇到yield,就会返回一个对象{value: x, done: true/false},然后暂停。
返回的value就是yield的返回值,done表示这个generator是否已经执行结束了。如果done为true,则value就是return的返回值。
- 另一个方法就是直接调用for … of循环迭代generator对象,这种方法不需要自己判断done。
'use strict'
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 0;
while (n < max) {
yield a;
[a, b] = [b, a + b];
n ++;
}
return;
}
for (var x of fib(10)) {
console.log(x); // 依次输出0, 1, 1, 2, 3, …
}
yield*
yield* 这种语句让我们可以在Generator函数里面再套一个Generator, 当然你要在一个Generator里面调用另外的Generator需要使用: yield* 函数;
这种语法
function* foo() {
yield 0;
yield 1;
}
function* bar() {
yield 'x';
yield* foo();
yield 'y';
}
for (let v of bar()){
console.log(v);
};
实际使用
ajax的异步处理, 利用生成器的特性,不但可以用于ajax的异步处理, 也能够用于浏览器的文件系统filesystem的异步:
<html>
<head>
<meta charset="utf-8">
<script src="//cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js"></script>
</head>
<body>
<script>
"use strict";
function* main() {
var result = yield request("http://www.filltext.com?rows=10&f={firstName}");
console.log(result);
//do 别的ajax请求;
}
function request(url) {
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
var data = JSON.parse(r.responseText);
//数据成功返回以后, 代码就能够继续往下走了;
it.next(data);
};
r.send();
}
var it = main();
it.next();
console.log("执行到这儿啦");
</script>
</body>
</html>
以上代码中的console.log(“执行到这儿啦”);先被执行了, 然后才出现了ajax的返回结果, 也就说明了Generator函数是异步的了;