事件循环

102 阅读2分钟

1. 为什么js在浏览器中有事件循环机制

  • js是单线程的
  • event loop

2. 两种任务

  • 宏任务:整体代码 setTimeout, setInterval, I/O操作
  • 微任务:new Promise().then , MutationObserver(前端的回溯)

3. 为什么要有微任务的概念,只有宏任务可以吗?

  • 宏任务 先进先出的原则执行

4. Node中的事件循环和浏览器中的事件循环有什么区别?

  • 宏任务的执行顺序
     1. timers 定时器:执行以及安排的setTimeoutsetInterval的回调函数
     2. pending callback 待定回调:执行延迟到下一个循环迭代的I/O回调
     3. Idel, prepare:仅系统内部使用
     4. poll:检索新的I/O事件,执行与I/O相关的回调
     5. check:执行setImmediate() 回调函数
     6. close callback:socket.on('close',()=>{})
  • 微任务和宏任务在node的执行顺序 Node v10及以前
  1. 执行完一个阶段中的所有任务
  2. 执行nextTick队列里的内容
  3. 执行完微任务队列的内容 Node v10以后 和浏览器的行为统一了

5. 事件循环面试题

  • 第一题
async function async1() {
    console.log('async1 start')
    await async2();            // 可以理解new Promise(()=>{ async2() })
    console.log('async1 end')  // .then(()=>{ console.log(async1 end) })
}
async function async2() {
    console.log('async2 start')
}
console.log('script start')
setTimeout(function (){
    console.log('setTimeout')
},0)
async1()
new Promise(resolve => {
    console.log('promise1')
    resolve()
}).then(function() {
    console.log('promise2')
})
console.log('script end')

/*
 script start 
 async1 start
 async2
 promise1 
 script end
 async1 end 
 promise2
 setTimeout
*/
  • 第二题
console.log('start')
setTimeout(()=>{
    console.log('children2')
    Promise.resolve().then(()=>{
        console.log('children3')
    })
})

new Promise(function(resolve, reject){
    console.log('children4')
    setTimeout(function() {
        console.log('children5')
        resolve('children6')
    },0)
}).then((res)=>{
    console.log('children7')
    setTimeout(()=>{
        console.log(res)
    })
})

/* 
start
children4 
第一轮宏任务结束,尝试清空微任务队列,发现没有微任务
children2
第二轮宏任务结束,尝试清空微任务队列
children3
children5
children7
children6
*/
  • 第三题
const p = function() {
    return new Promise((resolve, reject) => {
        const p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(1)
            })
            resolve(2)
        })
        p1.then(res => {
            console.log(res)
        })
        console.log(3)
        resolve(4)
    })
}

p().then(res => {
    console.log(res)
})
console.log('end')

// 3 end 2 4