Skip to content

promise

题目

以下代码,执行会输出什么

js
Promise.resolve().then(() => {
    console.log(0)
    return Promise.resolve(4)
}).then((res) => {
    console.log(res)
})

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

这道题很难

网上有很多文章介绍这道题,都没有给出清晰的答案。

被称为“令人失眠的”题目

回顾

  • 单线程和异步
  • 事件循环
  • 宏任务 微任务

then 交替执行

如果有多个 fulfilled 状态的 promise 实例,同时执行 then 链式调用,then 会交替调用
这是编译器的优化,防止一个 promise 持续占据事件

js
Promise.resolve().then(() => {
    console.log(1)
}).then(() => {
    console.log(2)
}).then(() => {
    console.log(3)
}).then(() => {
    console.log(4)
})

Promise.resolve().then(() => {
    console.log(10)
}).then(() => {
    console.log(20)
}).then(() => {
    console.log(30)
}).then(() => {
    console.log(40)
})

Promise.resolve().then(() => {
    console.log(100)
}).then(() => {
    console.log(200)
}).then(() => {
    console.log(300)
}).then(() => {
    console.log(400)
})

then 返回 promise 对象

当 then 返回 promise 对象时,可以认为是多出一个 promise 实例。

js
Promise.resolve().then(() => {
    console.log(1)
    return Promise.resolve(100) // 相当于多处一个 promise 实例,如下注释的代码
}).then(res => {
    console.log(res)
}).then(() => {
    console.log(200)
}).then(() => {
    console.log(300)
}).then(() => {
    console.log(300)
})

Promise.resolve().then(() => {
    console.log(10)
}).then(() => {
    console.log(20)
}).then(() => {
    console.log(30)
}).then(() => {
    console.log(40)
})

// // 相当于新增一个 promise 实例 —— 但这个执行结果不一样,后面解释
// Promise.resolve(100).then(res => {
//     console.log(res)
// }).then(() => {
//     console.log(200)
// }).then(() => {
//     console.log(300)
// }).then(() => {
//     console.log(400)
// })

“慢两拍”

then 返回 promise 实例和直接执行 Promise.resolve() 不一样,它需要等待两个过程

  • promise 状态由 pending 变为 fulfilled
  • then 函数挂载到 microTaskQueue

所以,它变现的会“慢两拍”。可以理解为

js
Promise.resolve().then(() => {
    console.log(1)
})

Promise.resolve().then(() => {
    console.log(10)
}).then(() => {
    console.log(20)
}).then(() => {
    console.log(30)
}).then(() => {
    console.log(40)
})

Promise.resolve().then(() => {
    // 第一拍
    const p = Promise.resolve(100)
    Promise.resolve().then(() => {
        // 第二拍
        p.then(res => {
            console.log(res)
        }).then(() => {
            console.log(200)
        }).then(() => {
            console.log(300)
        }).then(() => {
            console.log(400)
        })
    })
})

答案

题目代码输出的结果是 1 2 3 4 5 6

重点

  • 熟悉基础知识:事件循环 宏任务 微任务
  • then 交替执行
  • then 返回 promise 对象时“慢两拍”

PS:这里一直在微任务环境下,如果加入宏任务就不一样了

Released under the MIT License.