async函数的使用方式,直接在普通函数前面加上async,表示这是一个异步函数,在要异步执行的语句前面加上await,表示后面的表达式需要等待。async是Generator的语法糖,相比较Generator函数在以下四方面做了改进
async相对于Generator的优点
1.有内置执行器,不用调用next
Generator函数是需要调用next指令来运行异步的语句,async不需要调用next,直接像运行正常的函数那样运行就可以
2.有更好的语义化
语义化更明确,相比较于Generator的*和yield,async和await更明确。
3.await后面可以跟promise或者任意类型的值
yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
4.返回一个promise对象,可以调用.then
async直接返回一个promise对象,可以用then和cache来处理。
async function getStockPriceByName(name) {
let symbol = await getStockSymbol(name);
let price = await getPriceByName(symbol);
return price
}
getStockPriceByName('goog').then( (result)=> {
console.log(result);
}).catch((err)=>{
console.log(err)
})
上面的async异步函数遇到await会先返回一个Promise对象,等到异步操作执行完毕,才会根据结果来执行具体的回调函数。
async 函数多种形式
-
函数声明
async function foo() {}
-
表达式声明
var bar = async function () {}
-
对象声明
var obj = { async bazfunction(){ } }
-
箭头函数声明
var fot = async() => { }
await 语句
await后面是一个promise对象,如果不是,会转成一个resolve的promise对象
async function f() {
return await 123;
}
f().then(function (a) {
console.log(a);
})
await后面的promise对象,如果reject,则reject参数会被cache参数接收到,写不写return都可以,并且reject下面的代码不会执行,如果想下面的代码执行,必须用try cache包住
async function a() {
try{
await Promise.reject('出错了!')
}catch (e){
return await Promise.resolve('请重新填写')
}
}
a().then(function () {
console.log(err);
}).catch(function (err) {
console.log(err);
})
上面的代码如果不用try cache包裹reject,则下面的代码不会执行,并且reject语句是不用return返回的,resolve语句是需要用return返回;
async错误处理常用写法
如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。所以通常的处理方法有两种
用try catch包住可能会出错的部分
async function myFunction() {
try {
await somethingThatReturnsAPromise();
} catch (err) {
console.log(err);
}
}
另一种写法是对可能要出错的异步操作添加catch回调函数
async function myFunction() {
await somethingThatReturnsAPromise().catch((err)=> {
console.log(err);
})
}
多个await语句同时触发
let a=await getFoo();
let b=await getBar();
上面的两个方法都是异步操作,不存在依赖关系,所以我们可以同时触发,改写成下面的
//第一种写法
let [a,b]=Promise.all([getFoo(),getBar()])
//第二种写法
let aPromise=getFoo();
let bPromise=getBar();
let a=await aPromise;
let b=await bPromise;
async 函数的实现原理
async函数就是将执行器和Generator做为一个函数返回。
async function fn(){}
//等同于
function fn() {
return spawn(function* () {
})
}
function spawn(genF) {
/****
* 返回的是一个promise
*/
return new Promise(function(resolve, reject) {
var gen=genF(); //运行Generator这个方法;
/***
* 执行下一步的方法
* @param fn 一个调用Generator方法的next方法
*/
function step(fn) {
//如果有错误,则直接返回,不执行下面的await
try {
var next=fn();
}catch (e){
return reject(e)
}
//如果下面没有yield语句,即Generator的done是true
if(next.done){
return resolve(next.value);
}
// 如果下面还有yield语句,resolve继续执行递归执行gen.next(),reject则抛出错误
Promise.resolve(next.value).then((val)=>{
step(function(){ return gen.next(val) } )
}).catch((e)=>{
step(function(){ return gen.throw(e) } )
})
}
step(function () {
return gen.next();
})
});
}
参考阮大神的文章:http://es6.ruanyifeng.com/#do...