关于Promise执行顺序问题?

    Promise.resolve().then(res=>{
        console.log(1)
        return Promise.resolve()
    }).then(res=>{
        console.log(2)
    })
    Promise.resolve().then(res=>{
        console.log(3)
    }).then(res=>{
        console.log(4)
    }).then(res=>{
        console.log(5)
    }).then(res=>{
        console.log(6)
    })

    //打印
    // 1 
    // 3
    // 4
    // 5
    // 2
    // 6

打印2的位置 怎么解释呢

阅读 1.3k
3 个回答

第二次编辑:

根据看到的文章描述return Promise.resolve()这一步在原生实现中实际上有2个步骤:

  1. 将一个resolve结果是undefined的promise加入微任务队列
  2. 改变当前promise的状态(根据源码,似乎同样是一个微任务执行)

执行完以上之后,第一个promise才真正resolve,console.log(2)所在的回调函数才加入微任务队列,这才解释了为什么2在5和6之间打印
根据这个机制再来按顺序捋一遍,就符合了打印的顺序


第一次编辑:

实际用vscode调试发现和我的猜想不同

把问题的代码替换成相同效果的代码:

1    let p1
2    Promise.resolve()
3      .then(res => {
4        console.log(1)
5        return (p1 = new Promise((res, rej) => {
6          res()
7        }))
8      })
9      .then(res => {
10        console.log(2)
11      })
12    Promise.resolve()
13      .then(res => {
14        console.dir(p1)
15        console.log(3)
16      })
17      .then(res => {
18        console.log(4)
19      })
20      .then(res => {
21        console.log(5)
22      })
23      .then(res => {
24        console.log(6)
25      })

输出顺序和原代码一致:

1
Promise {[[PromiseState]]: 'fulfilled', [[PromiseResult]]: undefined, Symbol(async_id_symbol): 15, Symbol(trigger_async_id_symbol): 6}
3
4
5
2
6

在单步调试的时候,发现按行数的执行顺序实际是:

  2
  3
  12
  13
  4
  5 // return 执行
  6 // return的promise的resolve执行
  9 // console.log(2)所在的then执行
  14 // console.dir(p1),并且这时候p1就已经是fulfilled的状态了
  15 // console.log(3)
  17 // console.log(4)的then
  18 // console.log(4)
  20 // console.log(5)的then
  21 // console.log(5)
  10
  23
  24

令我没想到的是,return的promise没有在console.log(4)和console.log(5)的then执行后才resolve,相反,是先resolve然后console.log(2)的then都执行了才轮到4、5的then执行。看来then的执行和进入任务队列的先后没有必然关系,之前的回答还是从结果出发去猜过程,等我找找相关的资料再重新审视这个问题


原回答:
执行 return Promise.resolve() 后,其他微任务都已经入栈了,然后这个promise才从pending到resolved状态,所以console.log(2)所在的回调函数最后入栈执行

    Promise.resolve().then(res=>{
                    //^^^^ 它的返回值记为 promise_then
        console.log(1)
        return Promise.resolve()
             //^^^^^^^^^^^^^^^^^ 这个对象记为 promise_return
    }).then(res=>{
        console.log(2)
    })
    // 注意,promise_then 跟 promise_return 是两个不同的对象
   console.log(1) 入队
   -------------------
                             console.log(3) 入队
=========================================================
   console.log(1) 执行                               console.log(1)
   使用返回值 promise_return 去
   resolve promise_then。
   由于 promise_return 是一个
   promise ,于是入队一个任务
     调用 promise_return.then(),
     其回调为将 promise_then 设置
     为 fullfill
   ------------------------
                              console.log(3) 执行    console.log(3)
                              console.log(4) 入队
==========================================================
   promise_return.then() 执行
   由于 promise_return 已经
   fullfilled ,于是其回调作为
   一个任务入队:
     将 promise_return 置为
     fullfill
   -------------------------
                              console.log(4) 执行    console.log(4)
                              console.log(5) 入队
===========================================================
   promise_return 被设置为
   fullfilled,
   console.log(2) 入队
   --------------------------
                              console.log(5) 执行    console.log(5)
                              console.log(6) 入队
===========================================================
   console.log(2) 执行                               console.log(2)
   --------------------------
                              console.log(6) 执行    console.log(6)

所有的问题都源自自己的不规范,什么好人会这么写

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏