ES6提供了三种异步编程的解决方案,分别是Promise对象,Generator函数和async函数。Promise对象在之前的文章中(https://blog.csdn.net/qq_26834399/article/details/79701757)已经有过讲解。今天主要介绍一下Generator和async函数,以及三者解决异步处理的区别和联系。
Generator就是一个封装好的异步任务函数,有两个区别于普通函数的特征。一是在function关键字与函数名之间有个*,二是函数内部通过yield语句标明异步操作。只有通过next方法才能使函数执行,代码执行过程中,每次遇到yield或return都会暂停执行,直到再次执行next方法。每次执行next都会返回一个对象。
{
value:'', //当前执行代码的返回值
done:false //布尔值,Generator函数是否执行完
}
下面是使用Generator函数实现异步操作的例子
function* gen(){
var result = yield Promise.resolve({"name":"Annie"})
console.log("in gen :",result);
}
var g=gen();
var r=g.next();
console.log("out gen",r)
r.value.then(function(data){
console.log("in r then",data);
g.next({"name":"Keith"});
})
例子中,使用Promise来模拟一个异步操作,当第一次执行next的时候,返回值是一个value为Promise对象的,done为false的遍历器(Iterator)对象。在promise的then中再次执行next,则继续执行generator函数中的代码。其中next接受的参数,可以传入generator函数中,作为上一阶段异步任务的返回结果。执行结果如下:
由上面的例子可以看出,使用Generator函数实现异步任务,需要手动执行next才能执行下去,如何能让代码自动执行呢?这时就用到了async函数。async就是Generator函数的语法糖,对Generator函数进行了包装和处理。将Generator函数的*换成了async,yield换成了await,语义更明确。且增加了内置执行器,无需再执行next,代码就可以自动执行并输入最后的结果。
上述例子可使用async改写
async function gen(){
var result = await Promise.resolve({"name":"Annie"})
console.log("in gen :",result);
}
var r=gen();
console.log("out gen",r)
r.then(function(){
var data = {"name":"Keith"};
console.log("in r then",data);
return data
})
改写后,无需再使用next执行代码,在promise状态由pending变为resolved后,async函数中后面的代码也自动执行了,执行结果如下
总结来说,Promise的写法,需要暴露Promise的API,then、catch、finally等;Generator函数必须自定义一个自执行器,且保证每个yield语句后的表达式返回的都是Promise对象;async实现最简洁,最语义化。