sisterAn/JavaScript-Algorithms

编程题:以下输出顺序多少 (setTimeout 与 promise 顺序)

sisterAn opened this issue · 6 comments

setTimeout(() => console.log(0))
new Promise((resolve) => {
  console.log(1)
  resolve(2)
  console.log(3)
}).then(o => console.log(o))

new Promise(resolve => {
  console.log(4)
  resolve(5)
}).then(o => console.log(o)).then(() => console.log(6))

可参考 从一道面试题谈谈对 EventLoop 的理解

1 3 4 2 5 6 0

1 3 4 2 5 6 0

javascript明明是单线程同步语言,但是却能实现异步效果,什么原因呢?
这是因为其通过事件循环,把代码运行中的任务分为了宏任务以及微任务。
在执行下一次事件循环之前会先把当前的微任务队列执行清空,再把宏任务队列执行清空。
首先你需要知道的是setTimeout产生的是宏任务,promise 产生的是微任务。
之后我们观看代码知道
微任务队列:['promise1', 'promise2'],宏任务队列:['setTimeout']
执行promise1,打印#1,在微任务队列里推进promise1Resolve,打印#3
微任务队列:['promise2', 'promise1Resolve'],宏任务队列:['setTimeout']
执行promise2,打印#4,在微任务队列里推进promise2Resolve
微任务队列:[ 'promise1Resolve', 'promise2Resolve'],宏任务队列:['setTimeout']
执行promise1Resolve,打印#2
执行promise2Resolve,打印#5,在微任务队列里推进promise2ResolveThen
微任务队列:['promise2ResolveThen'],宏任务队列:['setTimeout']
执行promise2ResolveThen,打印#6
微任务队列:[],宏任务队列:['setTimeout']
执行setTimeout,打印#0

更详细的了解宏微任务可以点这里

@qianbaiduhai new Promise((resolve) => { console.log('1') }) 中的语句是同步语句,会立即执行的,不会放入微任务队列,resolve 之后才会进队列。可以在两个 promise 之间放一个 log 看看

/**
 * 1. 分析以下程序段的输出顺序
 * 主要是考察微任务 宏任务
 */
setTimeout(()=>console.log(0))
new Promise((resolve)=>{
    console.log(1)
    resolve(2)
    console.log(3)
}).then(res=>console.log(res))
new Promise((resolve)=>{
    console.log(4)
    resolve(5)
}).then(res=>console.log(res)).then(()=>console.log(6))
console.log(8)
Promise.resolve(7).then(res=>console.log(res))
/**
 * 分析:1 3 4 2 5 6 0
 * 1. setTimeout放到宏任务队列
 * 2. 立即执行new Promise 1 3  then放到微任务队列
 * 3. 立即执行new Promise 4 then放到微任务队列
 * 4. 循环微任务队列 2 5 6 
 * 5. 循环宏任务队列
 */
/**
 * 1. 分析以下程序段的输出顺序
 * 主要是考察微任务 宏任务
 */
setTimeout(()=>console.log(0))
new Promise((resolve)=>{
    console.log(1)
    resolve(2)
    console.log(3)
}).then(res=>console.log(res))
new Promise((resolve)=>{
    console.log(4)
    resolve(5)
}).then(res=>console.log(res)).then(()=>console.log(6))
console.log(8)
Promise.resolve(7).then(res=>console.log(res))
/**
 * 分析:1 3 4 2 5 6 0
 * 1. setTimeout放到宏任务队列
 * 2. 立即执行new Promise 1 3  then放到微任务队列
 * 3. 立即执行new Promise 4 then放到微任务队列
 * 4. 循环微任务队列 2 5 6 
 * 5. 循环宏任务队列
 */

1 3 4 8 2 5 7 6 0