基础执行顺序

先走主进程,再走微任务,再走宏任务。nodejs中,微任务只能有1000个,多出的只能下次事件循环再执行。
宏任务:setTimeout,setInterval,requestAnimationFrame
微任务:Promise,queueMicrotask

宏任务与微任务嵌套

  1. 宏任务套微任务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    console.log(1)
    setTimeout(()=>{
    console.log('宏任务1')
    queueMicrotask(()=>{
    console.log('微任务2')
    })
    })
    setTimeout(()=>{
    console.log('宏任务2')
    queueMicrotask(()=>{
    console.log('微任务3')
    })
    })
    queueMicrotask(()=>{
    console.log('微任务1')
    })
    console.log(2)

    // 被宏任务嵌套的微任务,在宏任务后执行,并不会有插队现象
    // 1 2 微任务1 宏任务1 微任务2 宏任务2 微任务3
  2. 微任务嵌套宏任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
console.log(1)
setTimeout(()=>{
console.log('宏任务1')
queueMicrotask(()=>{
console.log('微任务2')
})
})
queueMicrotask(()=>{
console.log('微任务1')
setTimeout(()=>{
console.log('宏任务2')
})
})
console.log(2)

// 微任务嵌套宏任务,也是不会有插队现象
// 1 2 微任务1 宏任务1 微任务2 宏任务2
  1. 微任务嵌套微任务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    console.log(1)
    queueMicrotask(()=>{
    console.log('微任务1')
    queueMicrotask(()=>{
    console.log('微任务2')

    })
    })
    queueMicrotask(()=>{
    console.log('微任务3')

    })

    console.log(2)

    // 1 2 微任务1 微任务3 微任务2
  2. 宏任务套宏任务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    console.log(1)
    setTimeout(()=>{
    console.log('宏任务1')
    setTimeout(()=>{
    console.log('宏任务2')
    })
    })
    setTimeout(()=>{
    console.log('宏任务3')
    })
    console.log(2)

    // 1 2 宏任务1 宏任务3 宏任务2

Promise不一样的事件队列

  1. then是个黑盒子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    console.log(1)
    Promise.resolve('x').then(()=>{
    console.log('微任务1')
    Promise.resolve('x').then(()=>{
    console.log('微任务2')
    })
    }).then(()=>{
    console.log('微任务3')
    })
    console.log(2)
    // then会导致事件插队,会使微任务2插队到微任务3前面(浏览器和Node11以上会插队)
    // 1 2 微任务1 微任务2 微任务3
  2. resolve也是个黑盒子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    Promise.resolve('x').then(()=>{
    console.log(1)
    }).then(()=>{
    console.log(3)
    }).then(()=>{
    console.log(5)
    }).then(()=>{
    console.log(7)
    }).then(()=>{
    console.log(9)
    })

    Promise.resolve('x').then(()=>{
    console.log(2)
    }).then(()=>{
    console.log(4)
    }).then(()=>{
    console.log(6)
    }).then(()=>{
    console.log(8)
    }).then(()=>{
    console.log(10)
    })
    // then的实现就是如此,不知道原理
    // 1 2 3 4 5 6 7 8 9 10

    Promise.resolve('x').then(()=>{
    console.log(1)
    }).then(()=>{
    console.log(3)
    return Promise.resolve(3,5)
    }).then(()=>{
    console.log(5)
    }).then(()=>{
    console.log(7)
    }).then(()=>{
    console.log(9)
    })

    Promise.resolve('x').then(()=>{
    console.log(2)
    }).then(()=>{
    console.log(4)
    }).then(()=>{
    console.log(6)
    }).then(()=>{
    console.log(8)
    }).then(()=>{
    console.log(10)
    })
    // 单独调用resolve,一个resolve推迟两个时序,resolve实现就是如此,不知道原理
    // 1 2 3 4 6 8 5 10 7 9

NodeJs的事件循环

  1. NodeJs单独的任务
    宏任务:rs.readFile(path,fn)
    微任务:setImmediate,process.nextTick(在)

  2. NodeJs事件循环有6个步骤
    [1] timers : 处理setTimeout
    [2] I/O callbacks
    [3] 准备阶段
    [4] poll(轮询阶段):访问操作系统的相关准备是否完毕
    [5] check : 处理setImmediate
    [6] close callbacks

  3. setTimeout和setImmediate

1
2
3
4
5
6
setTimeout(()=>{
console.log('timeout')
})
setImmediate(()=>{
console.log('immediate')
})

答案不唯一,事件循环是用C++写的,应用是JS的,有可能是C++先启动的,也有可能是JS先启动,说白了,这两件事情没关系

1
2
3
4
5
6
7
8
9
10
setTimeout(()=>{
setTimeout(()=>{
console.log('timeout')
})
setImmediate(()=>{
console.log('immediate')
})
},1000)
// immediate timeout
// 这样等于是JS慢一点执行,所以一定是immediate在前