eventloop(事件循环)

·  阅读 380

进程 和 线程

  1. 进程

描述了cpu在运行指令及加载和保存上下文所需要的时间

  1. 线程

进程中更小的单位,描述的是执行一段指令所需要的时间

JS是一门单线程语言,JS是单线程带来什么好处

js引擎在js运行时会阻塞UI的渲染(渲染引擎的工作) == js引擎线程 和渲染页面的线程是互斥的 因为js可以修改dom结构,如果在js执行的时候UI线程还在工作,就可能导致不安全的UI渲染,得益于js是单线程,可以达到节省运行内存,节约上下文切换的时间

事件循环(eventloop)是什么?

上面提到了,js语言是一门单线程语言,在一定时间内只能执行一条指令,js代码又分为同步代码和异步代码,在事件循环中同步代码是先执行的,异步代码(宏任务和微任务)在同步代码执行完以后在执行。

执行过程:

  1. 同步代码进入主线程立刻执行,异步代码进入event table事件中并注册函数,

  2. 当指定的事情完成时,Event Table会将这个函数移入Event Queue(事件队列)。

  3. 当同步代码执行完以后(主线程内的任务执行完毕为空),(读取异步函数)会去Event Queue读取对应的函数,进入主线程执行。

  4. 上述过程会不断重复,也就是eventloop事件。

15fdd88994142347 .png 此图借用别的作者的

接下来我们使用代码来分析:

setTimeout(()=>{
console.log('我是定时器里面的代码')
})
console.log('我是同步代码')
复制代码

image.png

结论:同步代码先执行,异步代码等同步代码执行完在执行

上面提到主线程上的同步代码执行完后,异步代码会去到主线程上去执行。而异步任务也分为(宏任务和微任务) 贴一段写好的代码:

setTimeout(() => {
    console.log('定时器');
    new Promise((reslove) => {
        console.log('setTimeout Promise');
        reslove()
    }).then(() => {
        console.log('setTimeout then');
    })
})
new Promise((reslove) => {
    console.log('Promise');
    reslove()
}).then(() => {
    console.log('then');
})
console.log('sss');
复制代码

在这段代码中,有同步任务和异步任务,我们先来区分一下同步任务和异步任务(在这段代码中异步任务包含了同步任务)

  1. 同步任务:-. 单独的console.log -. new Promise

  2. 异步任务:setTimeout,new Promise后面接的.then()

  3. 把异步任务细分 :1. 宏任务:setTimeout 2. 微任务 :.then()

分析代码:(微任务会比宏任务先执行)

代码是从上往下读取的,第一个setTimeout被放入异步任务(宏任务里面,具体不说了,settimeout里面的代码再说),然后第一个newPromise是同步任务先执行,输出Promise,后面的.then()(这是一个微任务)被放入事件队列(都说了是队列,那肯定是先进去的先执行),然后console.log是同步任务,进入主线程先执行输出sss,前面的异步任务在等待。主线程上同步任务执行完毕,异步任务进入主线程,微任务先执行,根据队列里的注册函数顺序,先执行微任务.then()输出then,微任务执行完了,宏任务执行,setTimeout里面还同步代码和异步代码,按照上面的执行方法再来一遍。(不重复了),直接输出定时器setTimeout PromisesetTimeout then

下面我们来总结一下:宏任务(macrotask)和微任务(microtask)

有哪些是宏任务:script,setTimeout,setInterval,setImmediate,I/O,promise 哪些是微任务:process.nextTick,promise.then,MutationObserver

强调一下:Promise是宏任务(同步执行),但Promise 的回调函数属于异步任务,会在同步任务之后执行(比如说 then、 catch 、finally)。

分类:
前端
标签:
分类:
前端
标签: