使用async/await用同步方式去写异步代码:
用 promise.then 也是相当复杂,虽然整个请求流程已经线性化了,但是代码里面包含了大量的 then 方法,使得代码依然不是太容易阅读。基于这个原因,ES7 引入了 async/await,这是 JavaScript 异步编程的一个重大改进,提供了在不阻塞主线程的情况下使用同步代码风格编写异步代码,并且使得代码逻辑更加清晰。
async/await=Promise+生成器应用(微任务+协程应用)
async是一个异步执行并隐式返回promise对象作为结果的函数。
await后面要跟一个promise实例对象
面试常考打印输出题:
async function foo() {//声明
console.log(1)//进到foo协程后先打印1
let a = await 100//当执行到await 100时,会默认创建一个 Promise 对象,JavaScript 引擎会将该任务提交给微任务队列microtask1,然后 JavaScript 引擎会暂停当前foo协程的执行,将主线程的控制权转交给父协程执行,同时会将 promise_ 对象返回给父协程。主线程的控制权已经交给父协程了,这时候父协程要做的一件事是调用 promise_.then 来监控 promise 状态的改变。接下来继续执行父协程的流程,这里执行console.log(3)打印出来 3。随后父协程将执行结束,在结束之前,会进入微任务的检查点,然后执行微任务队列,微任务队列中有resolve(100)的任务等待执行,执行到这里的时候,会触发 promise_.then 中的回调函数,如下所示:
//promise_.then((value)=>{
//将主线程控制权交给foo协程,并将value值传给协程
//})
//该回调函数被激活以后,会将主线程的控制权交给 foo 函数的协程,并同时将 value 值传给该协程。foo 协程激活之后,会把刚才的 value 值赋给了变量 a,然后 foo 协程继续执行后续语句,执行完成之后,将控制权归还给父协程。
console.log(a)
console.log(2)
}
console.log(0)//首先打印0
foo()//进到foo协程
console.log(3)
//0,1,3
//100,2
async function foo() {//声明
console.log('foo')
}
async function bar() {//声明
console.log('bar start')
await foo() //执行foo 、输出'foo',创建一个 Promise返回给主协程
console.log('bar end')// 将返回的promise添加到微任务队列microtask1
}
console.log('script start')//直接输出
setTimeout(function () {
console.log('setTimeout')
}, 0)//宏任务macrotask1
bar();//进到bar协程
new Promise(function (resolve) {
console.log('promise executor')
resolve();
}).then(function () {
console.log('promise then')//微任务microtask2
})
console.log('script end')
//script start 'bar start' foo 'promise executor' 'script end'
//'bar end' 'promise then'
//'setTimeout'
async function async1(){//声明
console.log('async1 start')
await async2()
console.log('async1 end')//随后父协程将执行结束,在父协程结束之前,会进入微任务的检查点,然后执行微任务队列,微任务队列中有任务等待执行,执行到这里的时候,会触发 promise_.then 中的回调函数,
async function async2(){//声明
console.log('async2 start')
return new Promise((resolve, reject) => {
resolve()
console.log('async2 promise')
})
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
}, 0);//宏macrotask1
async1()
new Promise(function(resolve){
console.log('promise1')
resolve()
}).then(function(){
console.log('promise2')//microtask1
}).then(function(){
console.log('promise3')//microtask2
})
console.log('script end')
//'script start' 'async1 start' 'async2 start' 'async2 promise' 'promise1' 'script end'
// 'promise2' 'promise3' 'async1 end'
//'setTimeout'