一、Generator
概念: Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同;[引入阮一峰老师的《ES6的入门》]
形式: 在Generator函数中,有yield表示不同的状态,在函数声明后要加上 *
function * fn(){
yield'1';
yield'2';
return '3'
}
var fun=fn()
看一下运行情况
可以看出与普通函数并不一样,这是因为Generator函数返回的并不是函数内的return,而是返回函数内部状态的指针,也就是指向各个yield的指针,则可以使用遍历器对象的.next
来查看
fun.next();
fun.next();
fun.next()
可以看出,是从函数内部的第一个yield开始向下遍历状态,done表示遍历是否结束,当执行第三个fun.next()
时,函数内yield已经没有了,故遍历结束,dong=>false
其实我感觉Generator函数就是一个暂缓执行的函数,正常函数加上()就执行了,就算内部没有yield也是暂缓执行;
function * fn(){
console.log("1")
}
var fun=fn();
fun.next()
正常函数应该在给变量赋值时就已经返回return了,但是Generator函数调用了.next()
才执行内部操作
.next()的参数: 其参数表示的是上一个yield表达式的值,所以第一个执行的next不设置参数;
function * fn(x){
var a=yield x;
var b=2*(yield a);
console.log(b)
}
var fun=fn(3);
fun.next();
fun.next(2);
fun.next(3)
可以看出,fun.next(2)
中2是yield x
的值,fun.next(3)
中3是yield a
的值,所以最后输出的b只和.next(3)有关
for…of…
function * fn(){
yield 1;
yield 2;
yield 3;
yield 4;
return 5;
yield 6
}
for(let num of fn()){
console.log(num)
}
可以看出,当return之后(也就是对于内部指针来说,done=true)后,遍历不再进行。
- 应用: 说了这么多基础,接下来就是应用了,看概念就知道,他是关于异步操作的函数,而看到他的内部结构,不难发现,
- 他之所以能很好的进行异步操作,就在于他能控制函数操作的阶段。因为它本身是不执行的,调用next才执行一步yield,并且next还具有记忆功能,同时会返回该阶段的返回值。
{value:"",done:true}
- 还有他能够与外部进行数据交换,既能获取函数内部数据,也能像其中传递数据
fun.next(2)
,将2赋值给当前yield前一个yield表达式的值 - 同时能像别的异步函数一样,捕捉到错误。
- 他之所以能很好的进行异步操作,就在于他能控制函数操作的阶段。因为它本身是不执行的,调用next才执行一步yield,并且next还具有记忆功能,同时会返回该阶段的返回值。
function * fn(a){
try{
var b=yield a+1;
}catch(error){
console.log(error)
}
}
var fun=fn(1);
fun.next();
fun.throw("出错了")
- 案例
<button>抽奖</button>
<span>还剩3次抽奖机会</span>
<script>
var btn=document.getElementsByTagName("button")[0];
var span=document.getElementsByTagName("span")[0];
var start=begin(3);
btn.onclick=function(){
start.next()
}
function * begin(count){
while(count>0){
count--;
yield change(count)
}
}
function change(num){
span.innerText="还剩"+num+"次抽奖机会"
}
点击一次抽奖后:
点击两次抽奖后:
- 异步代码-----摘自阮一峰老师的Es6入门
var fetch = require('node-fetch');
function *gene(){
var url="https://api.github.com/users/github";
var result=fetch(url);
console.log(result.bio);
}
封装后
var g = gen();
var result = g.next();
result.value.then(function(data){
return data.json();
}).then(function(data){
g.next(data);
});
二、async await
async、await就是异步操作的语法糖而已。
- 用法: async返回一个Promise对象,使用then添加回调函数,当函数执行时,遇到await就会停止执行,等异步操作完成后再执行。
- 例子
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint('hello world', 1000);//=>一秒后输出“hello world”