【日常记录总结】event loop执行过程详解

163 阅读3分钟

引言

整理自慕课网双越老师课程。

开始之前,我们需要知道:

  1. event loop是什么?
  2. event loop用于解决什么问题?

大家都知道JS是单线程运行的,意味只能同步去做一些事,第一件事做好,才能继续做。但是一些事需要做很久,比如定时器,比如像后台请求一个api。那么等待的时间就被浪费了,更会造成JS执行卡顿等等。所以也就有了熟知的异步的概念,那么异步如何实现呢?异步又是基于回调实现的。归根结底,我们得要实现异步回调的问题,所以引出了今天的主题:event loop。

event loop

event loop 是异步回调的实现原理。

我们举一个简单的例子来模拟下JS的运行。

console.log('Hi')

setTimeout(function cb1() {
    console.log('cb1') // cb 即 callback
}, 5000)

console.log('Bye')

很明显会依次打印Hi,Bye,5秒后会打印cb1,setTimeout里执行的代码就是异步的。接下来我们通过这个例子,配合老师做的图来模拟下JS执行的过程。

如图可分为5部分:

  1. Browser console可以理解为我们浏览器的控制台,用于显示打印信息。
  2. Call Stack通常译作“调用栈”,用于调用js。
  3. Web APIs 比较好理解了,就是浏览器对一些方法ES6规范外的一些定义,例如settimeout等,这是属于浏览器的定义与js无关。
  4. Callback Queue就是字面意思,回调队列,我们异步执行的方法会以队列的形式放在这里。
  5. Event loop就是我们的主角啦---事件循环,当我们所有的同步事件处理完成后,会到Callback Queue中以轮询的方式去拿异步回调,然后推到Call Stack中。

image.png

第一步执行

console.log('Hi')

image.png

在Call Stack 执行JS语句,会在控制台中打印出来。当执行完后,会清空在Call Stack中的执行过的JS。如下图所示

image.png

第二步会执行这个定时器

setTimeout(function cb1() {
    console.log('cb1') // cb 即 callback
}, 5000)

如下图所示,在Call Stack中执行setTimeout(cb1()),之前我们说过,setTimeout并不是JS的api,它是由浏览器定义的api,那么他并不会立刻打印出来,会先到Web Apis中去执行,执行会发现需要等待5s,同时也是个异步的过程。 image.png

第三步会执行最后一个同步的js,这个与第一步同理了,就不贴图啦(节省大家流量。。。。)

console.log('Bye')

重点来了,我们的所有的同步代码已经全部执行完了,如何监听异步回调呢?这时候就该event loop上场了。当Call stack中所有的同步执行完后,会触发event loop不停的去执行,也就是轮询的效果。event loop执行什么呢?它会去callback queue中去拿代码,当然现在还是空的,因为我们定时器是5秒。

image.png

5秒后,我们的定时器中的函数cb1会被推到callback queue中,让event loop去执行,event loop执行这个cb1,把cb1推到call stack中,执行,打印出cb1,清除。

image.png