js运行机制--Event Loop

86 阅读4分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

前言

闲来无事来复习一下js的运行机制以及Event Loop,再这里做一个小小的总结,以便后续再复习,为接下来的面试做准备。js是一个脚本语言,也可以叫做解释性语言,它的主要用途是用于和用户的交互,操作DOM结构。我记得我进第一家公司的时候面试官问过我一个问题,js是单线程还是多线程?我当时懵了,我心想js能使用ajax并且同时还能执行别的内容,肯定是多线程,但他这样问我了那肯定不是多线程,于是我回答了单线程,幸运的是我回答对了,但事后才知道js为什么是单线程,以及我当时误以为多线程到底是怎么实现的。

js

js是一个单线程语言,之所以它是单线程是为了避免带来不必要的麻烦,比如,如果有两个进程,都是来操作dom的,那一个线程修改dom,一个线程删除dom,如果它们同时执行那就会出现问题了。

任务队列

用于js单线程的性质导致代码都是按顺序执行的,必须上面的任务完成了才能执行下边的任务,但如果遇到耗时的操作就要等非常久了,为了解决这个问题就把任务分为了两种,一种是同步任务,一种是异步任务。这里的同步任务会直接在主线程上排队执行,执行完一个才会执行下一个;异步任务不会进入主线程,而是进入“任务队列”,只有任务队列通知主线程,某个异步任务执行好了,该任务才会进入主线程执行。

js的巡行机制就是上述内容的不断重复

事件和回调函数

  • 任务队列其实是一个事件队列,当任务队列中的异步任务完成时就会在事件队列中添加一个事件,当有事件的的时候就说明可以进入“执行栈”了

  • 任务队列中的事件包含了IO事件、鼠标点击事件、页面滚动事件等。只要指定过回调函数,这些事件发生时就会进入“任务队列”,等待主线程的读取

  • 这里的回调函数就是那些耗时的操作,也就是被主线程挂起的部分,异步任务必须指定回调函数,当主线程开始执行异步任务的时候就是执行对应的回调函数

  • 任务队列是一个队列,所以是先进先出,因此排在前面的事件优先被主线程处理。只要执行栈一空任务队列中事件就会进入执行栈

Event Loop

主线程从任务队列读取事件队列的过程是一个不断重复的操作,这个重复的操作就叫做Event Loop。

核心点就是,js运行的时候都是先执行同步代码,再执行异步代码(任务队列),在这里要特别注意定时器,定时器会在最后执行也行,也就是在同步任务、任务队列都执行后才会执行定时器的回调函数(这里就会出现一种情况,如果定时器前边的任务也非常耗时,那么即使你设置了时间回调函数也不会按时执行)

宏任务、微任务

通过上面的内容我们已经知道js的运行机制就是先运行同步任务再运行异步任务(任务队列),但异步任务还分为宏任务和微任务。

微任务包括但不限于process.nextTick、promise.then()、promise.catch()

宏任务包括但不限于定时器、I/O、setImmediate、script(整体代码)

这里要记住的核心是微任务先于宏任务执行!!!

还要注意一点Promise的构造函数中的内容属于同步任务

总结

最后把整个执行过程和事件循环画了个简单的图,如下

image.png