如下代码能够用promise更好理解promise
async function a(){
console.log(1)
const w = await v
console.log(3)
return w
}
a()
console.log(2)
复制代码
相似于bash
先入栈执行a():
console.log(1)
遇到await v,假设v不是function,则后面都用promise包起来:
假设v是一个基本类型
finalPromise = Promise.resolve(v).then((res)=>{console.log(3);return res})
若v是一个promise
finalPromise = v.then((res)=>{console.log(3);return res})
而后扔出去给处理promise的线程执行:
return Promise.resolve(finalPromise)
扔出去后函数a出栈,继续执行:
console.log(2)
promise由其余线程执行,resolve后回调进入微任务堆栈,这已是主线程以后的任务了:
console.log(3)
return res
复制代码
注意:v8里面碰到await这一步说是suspend延迟,当v被resolve的时候会resume恢复到当前做用域那一步执行,我本身也不太懂里面的具体实现,这边这样理解若是有误但愿指正异步
每次在使用async和await的时候,尤为在使用forEach、有多个await的时候,对哪一个先执行很是混乱,但愿可以理清楚。async
reference:Faster async functions and promises函数
先看v8解释图:微服务
左边是原始代码,右边是解释后的代码。ui
接下来跟作数学题同样,首先定义几个定理:spa
定理一、Promise.resolve(promise) === promise为真线程
这个是根据下面promiseResolve这个函数得出的,图在下面
复制代码
定理二、async函数返回一个promise3d
因为函数v8的简易解释图最后没有return的操做,因此实现应该不太一致
但这必定是正确的哈!!!
返回的应该是函数最后的 resolvePromise(implicit_promise, w)
相似于 return Promise.resolve(w)
复制代码
定理三、await v 相似于 Promise.resolve(v)
根据v8图里面的: promise = promiseResolve(v)
若是v不是一个promise:
await v 相似于 Promise.resolve(v)会建立一个promise
若是v是一个promise:
根据定理1,返会的就直接是v这个promise
复制代码
定理四、await后面是function的话是会先执行function的
遇到函数都会先入栈执行吧?
复制代码
定理五、await所在做用域的await后面的代码,其执行时间都是在这个await返回的promise被resolve后,能够理解成放在then里面
官方是suspend、resume这种实现的,理解成放在这个promise的then里面若是有问题但愿及时指正
async function a(){
console.log(1)
const w = await v
console.log(3)
return w
}
根据定理二、3相似于
function a(){
console.log(1)
return Promise.resolve(
Promise.resolve(v).then((res)=>{console.log(3);return res})
)
}
根据定理1等价于
function a(){
console.log(1)
return Promise.resolve(v).then((res)=>{console.log(3);return res})
}
若是v是一个promise的话根据定理1等价于
function a(){
console.log(1)
return v.then((res)=>{console.log(3);return res})
}
复制代码
遇到await,当前做用域以后的代码执行若是不是function就都包起来扔出去等待异步执行,而后继续执行同步代码
const a=async (index)=>{
console.log("a0"+index)
await console.log("a1"+index)
console.log("a2"+index)
}
async function example () {
const nums = [2,2]
nums.forEach(async (num,index) => {
console.log(`forEach${index}`)
const b = await a(index)
console.log(index)
})
console.log('out')
}
example()
console.log('example finished')
复制代码
相似于
example进栈执行,forEach执行:
console.log('forEach0')
遇到await,await后面是function,入栈执行a():
console.log("a00")
又发现await且后面是函数,执行console.log:
console.log("a10"),返回undefined
变成await undefined,因而将其做用域后面的代码打包起来扔出去:
return promiseA = Promise.resolve(undefined).then(()=>{console.log("a2")})
扔出去等待异步执行
a出栈,返回的是promiseA,在example中变成await promiseA:
return promiseB = promiseA.then(()=>{console.log(b)})
打包起来扔出去等待异步执行
第一个forEach函数出栈,第二个入栈(forEach是同步过程):
重复上面几个步骤,假设最终是promiseC被扔出去
第二个forEach函数出栈,example出栈:
执行console.log('example finished')
主程序完成,清空微服务栈:
第一个forEach的promise chain(promiseB)的头部仍是第二个(promiseC)的头部先被resolve?
由于这边的都是当即resolve的
所以promiseB的then回调B一、promiseC的then回调C1前后被加入队列
执行B1的console.log("a20")
执行完返回一个被resolve的promise因而其then回调B2加入微服务队列尾部
执行C1的console.log("a21")
执行完返回一个被resolve的promise因而其then回调C2加入微服务队列尾部
执行B2的then的回调的console.log(0)
执行C2的then的回调的console.log(1)
最终结果
forEach0
a00
a10
forEach2
a01
a11
out
example finished
a20
a21
0
1
复制代码