用promise理解async、await
栏目: JavaScript · 发布时间: 5年前
内容简介:以下代码可以用promise更好理解类似于注意:v8里面碰到await这一步说是suspend延迟,当v被resolve的时候会resume恢复到当前作用域那一步执行,我自己也不太懂里面的具体实现,这边这样理解如果有误希望指正
以下代码可以用promise更好理解
async function a(){ console.log(1) const w = await v console.log(3) return w } a() console.log(2) 复制代码
类似于
先入栈执行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的时候,对哪个先执行非常混乱,希望能够理清楚。
解决问题
reference: Faster async functions and promises
先看v8解释图:
左边是原始代码,右边是解释后的代码。
接下来跟做数学题一样,首先定义几个定理:
定理
定理1、Promise.resolve(promise) === promise为真
这个是根据下面promiseResolve这个函数得出的,图在下面 复制代码
定理2、async函数返回一个promise
由于函数v8的简易解释图最后没有return的操作,所以实现应该不太一致 但这一定是正确的哈!!! 返回的应该是函数最后的 resolvePromise(implicit_promise, w) 类似于 return Promise.resolve(w) 复制代码
定理3、await v 类似于 Promise.resolve(v)
根据v8图里面的: promise = promiseResolve(v) 如果v不是一个promise: await v 类似于 Promise.resolve(v)会创建一个promise 如果v是一个promise: 根据定理1,返会的就直接是v这个promise 复制代码
定理4、await后面是function的话是会先执行function的
遇到函数都会先入栈执行吧? 复制代码
定理5、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 } 根据定理2、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回调B1、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 复制代码
以上所述就是小编给大家介绍的《用promise理解async、await》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 理解原型其实是理解原型链
- 要理解深度学习,必须突破常规视角去理解优化
- 深入理解java虚拟机(1) -- 理解HotSpot内存区域
- 荐 【C++100问】深入理解理解顶层const和底层const
- 深入理解 HTTPS
- 深入理解 HTTPS
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web性能权威指南
Ilya Grigorik / 李松峰 / 人民邮电出版社 / 2013-9 / 69
本书是谷歌公司高性能团队核心成员的权威之作,堪称实战经验与规范解读完美结合的产物。本书目标是涵盖Web 开发者技术体系中应该掌握的所有网络及性能优化知识。全书以性能优化为主线,从TCP、UDP 和TLS 协议讲起,解释了如何针对这几种协议和基础设施来优化应用。然后深入探讨了无线和移动网络的工作机制。最后,揭示了HTTP 协议的底层细节,同时详细介绍了HTTP 2.0、 XHR、SSE、WebSoc......一起来看看 《Web性能权威指南》 这本书的介绍吧!