async await关键字
async
async做为一个关键字放在函数的前面,表示函数是一个异步函数。async就是异步的意思。异步就是意味着函数的执行不会阻塞后面代码的执行
async/await是promise和generator的语法糖。只是为了让代码书写起来更流畅,增加可读性。
async/await是建立在promise之上的,并不能取代他的地位。
基本语法
async function basicDemo(){
let result = await Math.random();
console.log(result);
}
basicDemo();
函数执行之后返回一个promise对象
async timeout(){
return 'hello world';
}
async的语法很简单,就是在函数前面加上关键字,表示函数是异步的。async函数也是函数,跟普通函数的调用是一样的。
async timeout(){
return 'hello world';
}
console.log(timeout());
console.log('111');
由于async是非阻塞的,所以上一段代码中‘111’先被打印出来,假如我们打印timeout的执行结果,发现它是一个被resolved了的promise
所以async返回的是一个promise对象,如果要获取到‘hello world’,我们应该用then方法
async timeout(){
return 'hello world';
}
timeout().then(result => {
console.log(result);
})
console.log('111');
执行结果是先打印‘111’,再打印‘hello world’
async内部的实现原理是:如果async内部有返回值,当调用该函数的时候,内部会调用一个Promise.resolve()将它转化为一个promise对象做为返回。假如在函数内部抛出错误,那么就会调用Promise.reject()返回一个promise,这时修改timeout函数
async function timeout(flag){
if(flag){
return 'hello world';
}else{
throw 'failue'
}
}
console.log(timeout(true));
console.log(timeout(false));
如果函数内部抛出一个异常错误,那么可以用catch去捕获。
timeout(false).catch(err => {
console.log(err);
});
await
await是等待的意思,后面可以跟着任何的表达式,不过通常都是跟着一个promise对象的表达式。注意⚠️:await只能放在async的函数里面。
现在写一个函数,让它返回promise对象,该函数的作用是2s之后让数值乘以2;
function doubleAfter2seconds(num){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * 2);
},2000);
})
}
再写一个async函数,使用await关键字调用。await后面放着就是返回promise对象的一个表达式:
async test(){
let result = await doubleAfter2seconds(30);
console.log(result);
}
test();
函数执行遇到await的时候表示等一下,代码暂停,不往下执行,等到后面的promise执行完毕之后拿到promise resolve返回的值再继续往下。返回值赋值给result
async function testResult(){
let first = await doubleAfter2seconds(30);
let second = await doubleAfter2seconds(40);
let third = await doubleAfter2seconds(50);
console.log(first + second + third);
}
将异步的代码变成同步的,避免了回调地狱。
一个思考
promise中实现并发是使用promise.all(),那么async/await是如何实现并发的?我们知道await关键字会阻塞代码运行,直到返回数据。
总结
放在一个函数前面的async有两个作用:
- 使得函数总是返回一个promise
- 允许在则其中使用await
promise前面的await关键字能够使JavaScript等待,直到promise处理结束,然后: - 如果它是一个错误,异常就产生了,就像在那个地方调用了throw error一样
- 否则,它会返回一个结果,我们可以将它分配给一个值。
有了async/await可以很方便的处理异步,但是不能忘记这个语法糖是基于promise的,在顶层代码的时候还是要用到promise而不能用await,因为await只能包含在async函数里面。