这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
async/await
根据MDN的定义,async是一个通过异步执行并隐式返回Promise作为结果的函数。异步执行和隐式返回Promise怎么理解。
隐式返回:可以看到async标记的函数执行后最终返回的是一个Promise对象。
async function foo(){
return 2
}
console.log(foo()) //Promise {<fulfilled>: 2}
foo().then((val)=>{console.log(val))} //2
对应Promise的写法
function foo(){
return new Promise((resolve)=>{
resolve(1)
})
}
console.log(foo()) //Promise {<fulfilled>: 1}
foo().then((val)=>{console.log(val)}) //1
await,async函数返回的是一个Promise对象,结合下面代码体会一下await是什么
async function foo() {
console.log(1)
let a = await 100
console.log(a)
console.log(2)
}
console.log(0)
foo()
console.log(3)
结果是: 0 - 1 - 3 - 100 - 2
结合一下之前说的协程的概念, 此时外部环境就是父协程, 而foo就是子协程
-
首先执行了
console.log(0) -
然后父协程将线程执行权交给了foo协程, 由于foo 函数被async标记过, JavaScript 引擎会保存当前的调用栈等(相当于有个独立的调用栈)信息, foo协程执行了
console.log(1), 此时遇到了await 100, 此时foo协程创建了一个promiselet promise_ = new Promise((resolve,reject)=>{ resolve(100) })可以看到在 executor 函数中调用了 resolve 函数,JavaScript 引擎会将该任务提交给微任务队列.
然后JS引擎会暂停当前foo协程的执行, 将主线程的控制权交给父协程执行, 同时将这个新建的promise_对象返回给父协程 , 此时父协程还有一件事, 就是用promise_.then中的回调函数来监控promise_状态的改变
-
此时父协程就接着执行
console.log(3), 并且打印出来3 , 随后父协程即将执行结束, 在结束前, 就会检查是否有微任务, 开始执行微任务队列, 微任务队列中有一个resolve(100)的任务等待执行, Promise_执行之后的触发promise_.then 中的回调函数promise_.then((value)=>{ //回调函数被激活后将主线程控制权交给foo协程,并将vaule值传给协程 })该回调函数被激活以后,会将主线程的控制权交给 foo 函数的协程,并同时将 value 值传给该协程。foo 协程拿到主线程执行权后,会把得到的 value 值赋给了变量 a,然后 foo 协程继续执行后续语句
console.log(2),执行完成之后,将控制权归还给父协程。这么看来await就是promise.then
总结一下: await之后的行为实际上就是让子协程创建了一个promise.resolve(), 然后返回给了父协程微任务队列, 当父协程要执行微任务队列的时候, 触发promise_.then的回调函数, 然后在回调函数中将执行权和返回值都交给子协程 .