浏览器eventLoop和node eventLoop

3,380 阅读3分钟

今天我们来学习一下,浏览器的事件环(eventLoop)和node的事件环,它们之间有什么区别,这也是面试常问的知识,所以一定要仔细看哦,写的不好的地方,欢迎大家指正。

一、浏览器事件环

1、js是单线程的吗?

我们都知道js是单线程的,当然这句话说的不是很对,应该说它的主线程是单线程的。例如:ajax和setTimeout在浏览器中就会多开一条线程。

2、异步里的概念(宏任务和微任务)

在JavaScript中,任务被分为Task(又称为MacroTask,宏任务)和MicroTask(微任务)两种。它们分别包含以下内容:

宏任务:setTimeout   setInterval   setImmediate(ie下生效)   MessageChannel(消息通道) 

微任务:Promise.then    MutationObserver(监听dom节点更新完毕)    process.nextTick()(node的文法,比Promise.then执行的快)

我们来写代码证明一下,宏任务和微任务哪个执行比较快。

setTimeout(()=>{
    console.log('setTimeout')
},0)
Promise.resolve().then(()=>{
    console.log('promise')
})
promise  setTimeout //promise在setTimeout之前输入,证明Promise.then执行较快

3、js的执行顺序

代码从上到下执行,会先执行同步的代码,再执行微任务,等待宏任务有没有到时间,时间到了的宏任务放到宏任务队列,微任务执行完毕后,会从宏任务队列中取出一个宏任务去放到当前的浏览器的执行环境中执行,当前执行环境都执行完毕后,会先去清空微任务,下面我们来看一段代码

setTimeout(()=>{
    console.log('timeout1');
    Promise.resolve().then(data=>{
        console.log('then1')
    })
},0)
Promise.resolve().then(data=>{
    console.log('then2') 
    setTimeout(()=>{
        console.log('timeout2');    
    },0)
})
//then2 timeout1 then1 timeout2

二、node事件环

1、node.js中对于事件环的解释

我们先来看一张官方文档的图片,然后来解释它们都是干什么的。node的事件环和我们浏览器的不太一样,它给每一个任务都配了一个队列,如下图。


  • timers: 定时器setTimeout和seInterval的执行,将callback加入队列中。
  • pending callbacks: 一些I/O的callback,推迟到下一次循环中执行。
  • idle, prepare: 内部的一些事件。
  • poll: 轮循,i/o,回调,fs.readFile()。
  • check: setImmediate的callback执行。
  • close callbacks: 一,些关闭的回调函数,如socket。

其实我们需要关心的就是timers、poll、check这三个阶段。下面我们来说一下它们的执行顺序。

  • 默认,会从上到下依次执行,如果代码执行到poll后,发现check阶段没有,那就在poll在等待,等待times时间到达后,再清空代码。
  • 只到队列发生切换时,就会执行微任务。
  • poll的下一个阶段就是check,如果check队列中有东西的,会先执行check。

下面我们来看几段代码,实现一下我们上面的论证。

setTimeout(()={
    console.log("time1");
    process.nextTick(()=>{
        console.log("nextTick2");
    });
});
console.log("start")
process.nextTick(()=>{
    console.log("nextTick1");
    setTimeout(()={
        console.log("time2");
    });
});
//
//start nextTick1 time1 time2 nextTick2 //node11尽量和浏览器的相同
//start nextTick1 time1 nextTick2 time2 //node10会出现这种输出上

上面的代码在node10的版本里会输出两种不同的结果,node11里就只会输出第一种,node11在尽量的和浏览器相同。

setImmediate(()=>{
    console.log('setImmediate')
});
setTimeout(()=>{
    console.log('timeout')
})
//setImmediate timeout
//timeout setImmediate

上面的代码会出现这两种输出结果,不一定谁先输出谁后输出。

fs.readFile('./name.txt','utf8',()=>{
    setImmediate(()=>{
        console.log('setImmediate')
    });
    setTimeout(()=>{
        console.log('timeout')
    })
})
//setImmediate timeout

上面的代码就一定会先输出setImmediate,因为readFile在poll阶段,它的下一个阶段一定是check,所以一定会先输出setImmediate。

好了,我们的浏览器事件环和node事件环就说到这里了,不明白的小伙伴动手敲一下,就会好很好多哦。。。