async/await 执行顺序问题

发布于 2022-09-12 23:09:25 字数 1541 浏览 29 评论 0

题目描述

async function foo() {
    return Promise.resolve(300)
    // return 300 // ❓问题:上下两种写法执行结果不一致的原因是什么呢?return 300 不等价于 return Promise.resolve(300) 吗
}
// debugger
;(async function () {
    console.log("start") // 1. 立即执行函数 会先执行这一步
    const p1 = Promise.resolve(100)
    const data1 = await p1 // 2. 遇到 await 后面代码放入微任务队列 第一位
    console.log("data1", data1) // 5. 同步代码执行完成 进入微任务队列 打印 data1 100
    const data2 = await 200 // 5. 执行 Promise.resolve(200) 之后代码放入微任务队列 第三位
    console.log("data2", data2) // 7. 进入微任务队列 打印 data2 200 
    const data3 = await foo() // 8. 执行foo() 之后代码放入微任务队列第四位
    console.log("data3", data3) // 9. 打印
})()
const res = foo()
console.log(res) // 3. 继续执行同步代码 执行此句 打印一个 promise
res.then((data) => { // 4. 我认为这是promise的状态已经是resolve,所以应该放入微任务队列的第二个位置 ❓问题:但实际上并不是这样,为什么?
    // ⚠️ 这个要等res 完全resolved之后才会执行 ❓问题:到底什么时候会被resolved 呢?
    console.log("data", data) // 6.执行微任务队列第二位 打印 ❓问题:为什么 data 200 在data1 data2 之后打印, 在data3 之前打印呢?
})

当foo()内返回return Promise.resolve(300)时如下图

image.png

当foo()内返回return 300时如下图,这个图与我理想的执行结果一致

image.png

自己的思路

我的思路、执行顺序都在代码注释里

你期待的结果是什么?实际看到的错误信息又是什么?

我期待的结果是:foo()方法中代码为 return Promise.resolve(300) 的时候返回值如下

start
Promise {<fulfilled>: 300}
data1 100
data 300 // 这个应该 优先
data2 200 // 这个应该 落后 实际不对
data3 300

实际错误信息如上面的图一

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

信仰 2022-09-19 23:09:25

不好意思,来晚了。

问题的关键点是 async 的实现和 await 的实现不同,也可以说是语义不同,前者采用的 RESOLVE 语义,后者采用的是 Promise.resolve 语义,RESOLVE 语义比 Promise.resolve 语义,在处理 promise 要慢一拍。

我之前在博客里有提到类似的例子

const p1 = Promise.resolve(1)
const async1 = async () => {
  return p1
}
async1().then(res => {
  console.log(res)
})
p1.then(res => {
  console.log(2)
}).then(res => {
  console.log(3)
})

最终等价于

const p1 = Promise.resolve(1)
const async1 = () => {
  return new Promise(resolve => {
    return Promise.resolve().then(() => {
      p1.then(resolve)
    })
  })
}
async1().then(res => {
  console.log(res)
})
p1.then(res => {
  console.log(2)
}).then(res => {
  console.log(3)
})

就是解释的 async 的语义和实现问题,题主可以去翻一下就能明白了。

叫思念不要吵 2022-09-19 23:09:25

Promise.resolveasync 函数都可以看成是语法糖
你要的等价关系其实是这样:

Prmise.resolve(300)
//等价于
(function(x){
  return new Promise(function(ok){
    return ok(x)
  })
})(300)

async foo(){return 300}
//等价于
function(){
  function foo(){return 300}
  return new Promise(function(ok){
    return ok(foo())
  })
}

我相信这可以回答你 return 300return Promise.resolve(300)的区别;
虽然你可以一眼看出来, 但编译器是要按套路走的.
同样的 await 关键字后面不管跟什么, 都是要多套一层的.
至于后面问题,都和这些有关;

为什么编译器那么傻,不智能一点?
为了所有Promise实现能互通, ES6 的Promise 也遵从Promise/A+规则;
你可以脑补一下这段代码的结果;

var p1 = Promise.resolve(1)
p1.then = (ok)=>ok(2);
console.log(p1);
Promise.resolve(p1).then(console.log)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文