-一、Generator
作用:解决异步操作
1.Generator函数有多种理解角度。语法上,首先可以把它理解成是一个状态机,封装了多个内部状态。
2.执行Generator函数会返回一个遍历器对象,也就是说,Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次便利Generator函数内部的每一个状态。
3.形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内不适用yield表达式,定义不同的内部状态(yield在英语里的意思时候“产出”)。
function* helloWorldGenerator(){
yield 'hello';
yield 'world';//解决实际问题的时候,这里不是一个字符串换,而是一个promise异步操作。
return 'ending';
}
//如何调用一个Generator------看下面这句话。
var hw = helloWorldGenerator();
4.next
每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或者return语句)为止。
换言之,Generator函数是分段执行的, yield表达式是暂停执行的标记,而next方法可以恢复执行。
什么时候执行next你也不知道,要等到上一个状态完成。比如yield ‘包饺子’,那么现在的状态就是包饺子,包完饺子才能next。 yeild就像是提示我们可以开始包饺子啦这样的。
5.yield
由于Generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
小练习,注释和知识点在代码的注释之中哦
<script>
// function后面加*就是一个Generator了,一个生成器
// Generator是用一个同步的方法去描述异步操作的这么个东西。
function* dp() //比如我们现在想要进行一个包饺子的操作
{
// 先用字符串来代替哦
yield "maicai";
yield "huomian";
yield "bao";
yield "zhu";
return "chi";
// 注意每个yield都是异步操作,而generator本身是一个同步的操作,每个yield按顺序执行
}
var foo = dp();
console.log(typeof foo);
var a = foo.next();
console.log(a.value, a.done); //打印maicai,done的意思就是整个的这个过程完成没有,没完成所以是false
let b = foo.next();
console.log(b.value); //打印huomian
let c = foo.next();
console.log(c.value); //打印bao
let d = foo.next();
console.log(d.value); //打印zhu
let e = foo.next();
console.log(e.value); //打印chi
let f = foo.next();
console.log(f.value); //报错 f is undefined.
// generator 一旦到了结束,我们就不能获得刚开始的状态,除非我们新建一个对象,对于dp来说已经结束。
// 新建一个新的对象,不能继续用foo了
var foo2 = new dp();
for (let i of foo2) {
console.log(i);
}
</script>
小练习-用Generator实现斐波那契数列
<!-- 用Generator实现菲波那切数列 -->
<script>
function* fblq() {
let [now, next] = [0, 1];
while (1) {
yield now;
[now, next] = [next, now + next];
}
}
for (let i of fblq()) {
if (i > 1000000) break; //给一个范围,不要一直执行下去
console.log(i);
}
</script>
- 二、async
1.ES2017标准引入了async函数,是的异步操作变得更加方便
2.async是Generator函数的语法糖
const asyncReadFile = async function(){
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};