「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」。
通过个人的理解来简单讲述一下js中的事件循环机制。
首先我们要了解JavaScript是一个单线程的脚本语言,因为如果同时对同一个Dom节点进行添加和删除操作,那么就会出现问题,我该听谁的,具体怎么操作。
了解了js是一门单线程的脚本语言,我们来认识几个概念
- 主线程
- 执行栈
- 任务队列
- 宏任务 常见的宏任务:script全部代码、setTimeout、setInterval、setImmediate、I/O、UI Rendering。
- 微任务 常见的微任务:Process.nextTick、Promise。
注意 new Promise的过程属于同步任务,resove或者reject之后才算微任务。
主线程: 可以理解成js的首要任务,也可以方便理解成同步任务的先进先出。调用了,使用了同步任务就执行。
执行栈: 因为执行栈是一个先入后出的一个数据结构,为了便于理解,我们姑且先浅显的理解成有一个同步任务来了进入栈底马上执行它,然后释放。
任务队列: 任务队列的存在就是为了应对一些异步任务的存在,我们在执行一个任务如果迟迟等不到总不可能一直等待着,程序不接着往下进行。
宏任务和微任务 在这么我们都将其看作是异步任务,因为通俗理解主线程是在执行同步任务完成之后才会来执行宏任务和微任务。在这里我们通俗理解微任务的优先级比宏任务要高,先于宏任务执行。
接下来看一下一个初略的事件循环图
主线程首先执行完同步任务,然后会去任务队列中执行宏任务,如果在执行宏任务的过程中发现有微任务,这时候微任务比宏任务先执行。全部执行完成之后等待主线程调用,调用完成之后再去任务队列中查看是否还有异步任务有待执行,循环往复。
接下来我们看看先进后出的执行栈要怎么理解.
首先我们这么理解,当爷爷想喝酒的时候,他叫来了爸爸,让他去买酒,爸爸呢又把任务交给儿子让儿子去买酒,当儿子买到酒的那一刻买酒这件事情就结束了。所以我们将出栈看作是释放的一个过程。
当a函数调用了b函数,当b函数的调用完成,它的空间或者说这件事情就被释放,紧接着再释放a函数。
回到正题。看几个事件循环的问题。
第一题
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
分析一下:首先执行同步任务,显然console.log()先从上而下执行,那么就输出 'script start' 和 'script end',然后进入任务队列查看是否有无准备就绪的异步任务。进入任务队列我们发现第一个promise的resolve,记成微任务then1,此时微任务层级1完成他就排队等待主线程的调用,然后setTimeout就放到宏任务队列中等待,接着轮询,执行微任务1,有个微任务2丢到微任务队列,紧着着再轮询,执行微任务2,接着发现没有微任务了就看看有没有宏任务,发现了一个setTimeout 那么任务队列中等待执行的顺序就是 promise1,promise2,setTimeout。
所以全部的执行顺序就是'script start''script end' promise1 promise2 setTimeout
第二题
Promise.resolve().then(function(){
console.log('resolve1')
setTimeout(function(){
console.log('setTimeout1')
},0)
})
setTimeout(function(){
console.log('setTimeout2')
Promise.resolve().then(function(){
console.log('resolve2')
})
},)
首先resolve().then 发现一个微任务,丢到微任务队列中执行完毕,在事件队列等待,然后发现一个setTimeout函数2,放到宏任务队列中。然后轮询,调用微任务队列执行,打印resolve1,然后发现一个setTimeout函数1,丢到宏任务队列中,接着轮询,发现没有执行好的微任务等待调用,那么就按顺序执行宏任务队列,先执行setTimeout2,然后执行发现微任务resolve2,丢到微任务队列,接着轮询,执行resolve2最后setTimeout1,
所以内容的全部顺序为resolve1 setTimeout2 resolve2 setTimeout1
感谢读者大大的阅读,作为一个前端小白,写作的内容多少会有点瑕疵,如果写的文章有不好值得纠正的地方,欢迎各位读者大大们的指正和探讨。