微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JS事件循环机制Event loop 执行顺序

参考博文

博文1
博文2
练习1
练习2

为什么有事件循环

js是运行于浏览器的脚本语言,因其经常涉及操作dom,如果是多线程的,如果一个线程修改dom,另一个线程删除dom,那么浏览器就不知道该先执行哪个操作,所以js执行的时候会按照一个任务一个任务来执行,那么任务是怎么排列的呢
JS任务分为同步任务和异步任务。试想一下,如果js的任务都是同步的,那么遇到定时器、网络请求等这类型需要延时执行回调函数的任务会发生什么?页面会像瘫痪一下暂停下来等待这些需要需要时间的代码执行完毕,基于此,又引入了异步任务。异步任务分为宏任务和微任务。

  • 同步任务:同步任务不需要进行等待可立即看到执行结果,比如console
  • 异步任务:异步任务需要等待一定的时候才能看到结果,比如setTimeout、网络请求

为什么异步任务的事件中要区分宏任务和微任务

假设如果异步任务的回调是在操作dom,但是页面渲染也是一个任务,如果把dom渲染的任务排到异步任务的队尾,那么页面同样会出现瘫痪,所以js就规定一些可以插队完成的任务,这类型的任务称为微任务,比如说dom渲染,后面又引入promise.then。
在JS中宏任务队列只有一个,而每一个宏任务都有一个自己的微任务队列,每轮循环都是由一个宏任务+多个微任务组成。微任务是在执行宏任务的过程中产生的,因此每一个宏任务都对应着一个微任务队列。微任务队列可为空,即该宏任务执行过程中没有产生微任务。

宏任务和微任务有哪些,他们之间的优先级是什么

常见的宏任务有:
script(整体代码
setTimout
setInterval
setImmediate(node 独有)
requestAnimationFrame(浏览器独有)
IO/UI render(浏览器独有)
网络请求
new Promise(xxx)中xxx是同步代码
常见的微任务有:
process.nextTick(node 独有)
Promise.then()
Object.observe
MutationObserver
async
应注意的:
1、new Promise(xxx)中xxx是立即执行的(示例1)
2、在async/await中,在出现await出现之前,其中的代码也是立即执行的,
await XXX;中的 XXX 也是立即执行的,await XXX;之后的语句会被添加到微任务队列中。(示例1)
3、微任务队列中 process.nextTick的优先级最高(示例1)
4、宏任务队列中 setTimeout 比 setImmediate 优先级更高(示例2)
5、宏任务队列中 setTimeout 的执行优先级与其设置的时间有关(示例3)
6、宏任务队列中,若设置时间都为认时间,则优先级顺序为:
setTimeout/setInterval > IO/UI render(浏览器独有)> setImmediate(node 独有)

JS的执行顺序如何描述

1、将整个JS代码放入执行栈中,此时可将整个JS代码视为宏任务队列中第一个宏任务,也是唯一一个宏任务。
且在未开始执行时,微任务队列为空。
2、开始执行当前宏任务,执行过程中,同步任务自上而下依次执行,
异步任务中的宏任务被添加到宏任务队列(不一定放在队尾),微任务则被添加到微任务队列(不一定放在队尾)
3、执行完当前宏任务后,会在其对应的微任务队列中取出队首的微任务;
4、若执行微任务的过程中产生了宏任务,则会将产生的宏任务放入宏任务队列中(不一定放在队尾)
5、执行完当前微任务后,会接着去取微任务队列中的微任务,直到此微任务队列为空,则完成一次事件循环。
6、若宏任务队列不为空,则取出队首的宏任务,重复2-5的操作,直至宏任务队列为空。

示例1

async function fn() {
    console.log(1);
    await console.log(2);
    console.log(3);
}
fn()
new Promise(resolve => {  
        console.log(4)  
        resolve()
        console.log(5)
}).then(() => {
    console.log(6)
})
process.nextTick(() => {
    console.log(7)
})
// 输出 1 2 4 5 7 3 6

示例2

setTimeout(() => {
    console.log('setTimeout')
  })
setImmediate(() => {
    console.log('setImmediate')
  })
  //输出 setTimeout setImmediate

示例3

 //微任务产生的不同宏任务的优先级
new Promise(resolve => { // 第二个promise  
    console.log(1)  
    resolve()
}).then(function() {  
    setTimeout(() => {
          console.log(2)
        }, 4000)
}).then(function() {  
    setTimeout(() => {
        console.log(3)
      }, 2000)
}).then(function() {  
    setTimeout(() => {
        console.log(4)
      }, 1000)
})```
//输出 1 4 3 2

原文地址:https://www.jb51.cc/wenti/3282202.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐