用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解释图:

用promise理解async、await

左边是原始代码,右边是解释后的代码。

接下来跟做数学题一样,首先定义几个定理:

定理

定理1、Promise.resolve(promise) === promise为真

这个是根据下面promiseResolve这个函数得出的,图在下面
复制代码
用promise理解async、await

定理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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

因计算机而强大

因计算机而强大

[美]西摩 佩珀特 Seymour Papert / 梁栋 / 新星出版社 / 2019-1 / 38

本书有两个中心主题—— 孩子可以轻松自如地学习使用计算机; 学习使用计算机能够改变他们学习其他知识的方式。 (前苹果公司总裁 约翰·斯卡利) 最有可能带来文化变革的就是计算机的不断普及。 计算机不仅是一个工具,它对我们的心智有着根本和深远的影响。 计算机不仅帮助我们学习 ,还帮助我们学习怎样学习。 计算机是一种调解人与人之间关系的移情对象。 一个数学的头脑......一起来看看 《因计算机而强大》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具