一、async
async命令放在函数前使用,一个函数如果加上async,那么该函数就会返回一个Promise,async就是将函数返回值使用 Promise包裹了下,和then中处理返回值一样。
async function test() {
return "hello world"
}
console.log(test()) // -> Promise { 'hello world' }
二、await
await命令后面可以是Promise对象或值,如果是值,就会转到一个立即resolve的Promise对象。await关键字的返回结果就是其后面Promise执行的结果,可能是resolved或者rejected的值。在async函数中,如果有多个await关键字时,如果有一个await的状态变成了rejected,那么后面的操作都不会继续执行。
async function test() {
let value = await sleep()
}
三、优点
async是“异步”的意思,而await是“等待”的意思,组合起来就是等待异步完成,同时可以把异步转成同步。async 和 await 是异步极佳的解决方法,相比直接使用 Promise 来说,优势在于处理 then 的调用链,能够更清晰准确的写出代码,优雅地解决回调地狱问题。
四、缺点
滥用 async 可能会导致性能问题,因为 await 会阻塞代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低。
async function test() {
// 以下代码没有依赖性的话,完全可以使用 Promise.all 的方式
// 如果有依赖性的话,其实就是解决回调地狱的例子了
await ajax(url1)
await ajax(url2)
await ajax(url3)
}
console.log("我是不会被阻塞的!");
五、经典面试题
async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
async1();
console.log('hello')
很多小伙伴存在误区,认为await是把同步变为异步,执行顺序应该是这样
async1 start
async2
async1 end
hello
然而并不是,正确的执行顺序是
async1 start
async2
hello
async1 end
原因:
同步等待只会等待async中的await后边的代码,async外边的同步代码是不会被阻塞的,如代码中的console
执行顺序分析:
1.执行async1(),打印‘async1 start’;
2.执行 async2(),打印‘async2’(console.log会立即执行),返回一个promise,加入到微任务队列中,awwait等待promise执行完才继续往下走;
3.执行主任务上的 console.log('hello');
4.此时主任务代码空了,执行微任务里的promise,执行完继续执行console.log('async1 end')。