当前位置: 代码网 > it编程>编程语言>Javascript > JavaScript中的事件循环方式

JavaScript中的事件循环方式

2024年05月18日 Javascript 我要评论
js是单线程,非阻塞,试想如果是多线程,一个线程在某个dom节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,javascript就是单线程。js

js是单线程,非阻塞,试想如果是多线程,一个线程在某个dom节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,javascript就是单线程。

js的事件循环分为主线程(同步)和任务队列(异步),任务队列里又分为宏任务和微任务

1.宏任务(macro-task):

script(整体代码),settimeout,setinterval,setimmediate。

优先级: setimmediate > settimeout / setinterval 

2.微任务(micro-task):

promise,mutationobserve(观察dom树结构发生变化时,做出相应处理),process.nexttick(node.js 环境)。

优先级:process.nexttick > promise > mutationobserver

概述原理

同步>微任务>宏任务

1.宏任务、微任务都是任务队列,一段代码执行时,会先执行宏任务中的同步代码。

2.进行第一轮事件循环的时候会把js脚本当成一个宏任务来运行。

3.如果执行中遇到settimeout之类宏任务,那么就把这个settimeout内部的函数推入宏任务的队列中,下一轮宏任务执行时调用。

4.如果执行中遇到 promise.then() 之类的微任务,就会推入到微任务队列中,在本轮宏任务的同步代码都执行完成后,依次执行所有的微任务。

5.当执行完全部的同步脚本以及微任务队列中的事件,这一轮循环就结束了,开始第二轮循环,依次循环往复。

案例解析

<script>
settimeout(() => {
    console.log('4')
}, 100)
new promise((resolve) => {
    console.log('1')
    resolve("成功")
}).then(data => {
    console.log(data)
})
console.log('2')
</script>

解析

1.这段代码作为宏任务,进入主线程。

2.先遇到settimeout之类宏任务,那么就把这个settimeout内部的函数推入宏任务的队列中,下一轮宏任务执行时调用。

3.接下来遇到了promise,同步代码立即执行,回调函数分发到微任务队列中。

4.遇到console.log(‘2’),立即执行,查看有无微任务,有一个then的回调函数,立即执行。

5.第一轮宏任务执行结束。

6.开始第二轮宏任务,执行宏任务中的settimeout函数。

将以上代码升级下:

settimeout(() => {
    console.log('1') 
}, 1000)
new promise((resolve) => {
    console.log('2') 
    settimeout((params) => {
        resolve("4")
        console.log("3"); 
    }, 100)
}).then(data => {
    console.log(data) 
})
console.log('5') 

能否先将promise.then分发到微任务中?

答案是不能,因为只有resolve成功回调之后才能执行.then,而现在resolve在settimeout宏任务中,只有等settimeout执行完之后才能执行.then中的微任务 

解析

1.这段代码作为宏任务,进入主线程。

2.先遇到等待时间为1000ms的settimeout,记为s1,并且把这个settimeout内部的函数推入宏任务的队列中,下一轮宏任务执行时调用。

3.接下来遇到了promise,同步代码立即执行,但其内部包含一个等待时间为100ms的settimeout,记为s2,并且promise的resolve也在其中,也把它放在下一轮的宏任务中。

4.遇到console.log(‘5’),立即执行。

5.第一轮宏任务执行结束。查看当前有没有可执行的微任务,没有则执行宏任务。

6.开启第二轮宏任务,发现有两个宏任务,比较等待时间长短,时间短的先执行,先执行s2,发现其中有微任务promise.then,立即执行,再执行s1。

最后的执行顺序为2 5 3 4 1

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

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

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com