JavaScript中的事件循环方式

目录
  • 概述原理
    • 同步>微任务>宏任务
  • 案例解析
    • 能否先将promise.then分发到微任务中?

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)

相关推荐

  • 详解JS事件循环及宏任务微任务的原理

    目录 宏任务 微任务 事件循环 宏任务与微任务 微任务中创建宏任务 宏任务中创建微任务 宏任务中创建宏任务 微任务中创建微任务 总结 本质上来说,JavaScript是同步的.阻塞的.单线程语言,不管是在浏览器中还是nodejs环境下.浏览器在执行js代码和渲染DOM节点都是在同一个线程中,执行js代码就无法渲染DOM,渲染DOM的时候就无法执行js代码.如果按照这种同步方式执行,页面的渲染将会出现白屏甚至是报错,特别是遇到一些耗时比较长的网络请求或者js代码,因此在实际开发中一般是通过异步的方

  • Javascript单线程和事件循环

    目录 一.单线程 二.事件循环 三.事件循环的应用 四.使用代码来说明 五.setTimeout() 六.思考:劣质的优化 一.单线程 Javascript 是单线程的,意味着不会有其他线程来竞争.为什么是单线程呢? 假设 Javascript 是多线程的,有两个线程,分别对同一个元素进行操作: function changeValue() { const e = document.getElementById("ele1"); if (e) { e.value = "VAL

  • JavaScript 的setTimeout与事件循环机制event-loop

    目录 1.先说说我们都知道的setTimeout 2.再讲讲我们可能不知道的setTimeout event-loop 3. node中的时间循环执行顺序 4. 关于事件循环中的promise 1.先说说我们都知道的setTimeout setTimeout在我们写代码中会经常用到,不管是前端还是服务端,目的是延迟执行. setTimeout(() => { console.log('延迟执行'); },1000); 貌似没什么可讲的. 2.再讲讲我们可能不知道的setTimeout 我们可能遇

  • 一篇文章让你搞清楚JavaScript事件循环

    目录 前言 宏任务 微任务 事件循环 宏任务与微任务 总结 参考资料 前言 异步函数也是有执行顺序的.本质上来说,JavaScript是单线程语言,不管是在浏览器中还是nodejs环境下.浏览器在执行js代码和渲染DOM节点都是在同一个线程中,执行js代码就无法渲染DOM,渲染DOM的时候就无法执行js代码.如果按照这种同步方式执行,页面的渲染将会出现白屏甚至是报错,特别是遇到一些耗时比较长的网络请求或者js代码,因此在实际开发中一般是通过异步的方式解决. 什么是异步?js是一步一步执行代码的,

  • JavaScript事件循环同步任务与异步任务

    目录 前言 执行栈与任务队列 执行栈 任务队列 同步任务与异步任务 同步任务 异步任务 js的执行机制 结语 前言 首先,在学习js中同步异步的问题前,需要明白,js是单线程的,为什么它得是单线程的呢?这得从它的使用场景来看了,它主要是用来让用户与页面进行交互的吧.那么假设js是多线程的,在这个线程里面,用户点击某个按钮会增加一个DOM节点,在另一个线程里面,用户点击这个按钮又会删除一个DOM节点,那么此时js就不知道该听谁的了.那同步异步的出现又是为了什么呢?假设没有异步,那么我们在向服务器请

  • JavaScript中的事件循环方式

    目录 概述原理 同步>微任务>宏任务 案例解析 能否先将promise.then分发到微任务中? js是单线程,非阻塞,试想如果是多线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,JavaScript就是单线程. js的事件循环分为主线程(同步)和任务队列(异步),任务队列里又分为宏任务和微任务 1.宏任务(macro-task): script(整体代码),setTimeout,setInterval,setI

  • JavaScript中绑定事件的三种方式及去除绑定

    在JavaScript中,有三种常用的绑定事件的方法 第一种办法 函数写在结构层里面 非常不好,使页面很混乱,行为与结构得不到分离 <input type="button" onclick="func();"> 绑定事件的第二种办法 好处:行为与结构开始分离 缺点: 第二种绑定方式中只能给一个时间绑定一个处理函数 即.onclick = fn1;  .  onclick = fn2 最终的效果是onclick = fn2 <select name=

  • JavaScript中为事件指定处理程序的五种方式分析

    本文实例讲述了JavaScript中为事件指定处理程序的五种方式.分享给大家供大家参考,具体如下: JavaScript和HTML之间的交互是通过事件实现的. IE9.Firefox.Opera.Sarifi.Chrome都已经实现了DOM2级事件模块的核心部分,IE8是最后一个仍然使用其专有事件系统的主要浏览器. 事件流: 事件流描述的是从页面中接受事件的顺序,但IE和Netscape却提出了完全相反的事件流的概念,IE的事件流是事件冒泡流,而Netscape的事件流是事件捕获流. 1) 事件

  • JavaScript中错误正确处理方式小结你用对了吗

    JavaScript的事件驱动范式增添了丰富的语言,也是让使用JavaScript编程变得更加多样化.如果将浏览器设想为JavaScript的事件驱动工具,那么当错误发生时,某个事件就会被抛出.理论上可以认为这些发生的错误只是JavaScript中的简单事件. 本文将会讨论客户端JavaScript中的错误处理.主要介绍JavaScript中的易犯错误.错误处理.异步代码编写等内容. 下面就让我们一起看看如何正确处理JavaScript中的错误. Demo演示 本文中使用的demo可以在GitH

  • JavaScript中的事件委托及好处

    1,什么是事件委托:通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件. 也就是:利用冒泡的原理,把事件加到父级上,触发执行效果. 好处呢:1,提高性能. 我们可以看一个例子:需要触发每个li来改变他们的背景颜色. <ul id="ul"> <li>aaaaaaaa</li> <li>bbbbbbbb&l

  • 一文详解JS中的事件循环机制

    目录 前言 1.JavaScript是单线程的 2.同步和异步 3.事件循环 前言 我们知道JavaScript 是单线程的编程语言,只能同一时间内做一件事,按顺序来处理事件,但是在遇到异步事件的时候,js线程并没有阻塞,还会继续执行,这又是为什么呢?本文来总结一下js 的事件循环机制. 1.JavaScript是单线程的 JavaScript 是一种单线程的编程语言,只有一个调用栈,决定了它在同一时间只能做一件事.在代码执行的时候,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行.在

  • JavaScript中定义类的方式详解

    本文实例讲述了JavaScript中定义类的方式.分享给大家供大家参考,具体如下: Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门灵活的语言,下面我们就看看没有关键字class的Javascript如何实现类定义,并创建对象. 一.定义类并创建类的实例对象 在Javascript中,我们用function来定义类,如下: function Sh

  • 理解JavaScript中worker事件api

    如果你不是很了解Event事件,建议先这篇文章<理解javascript中DOM事件>. 首先,我们需要实例一个Worker的对象,浏览器会根据新创建的worker对象新开一个接口,此接口会处理客户端与indexedDB数据库之间的通信.这里的数据库是指浏览器数据库.如果,你需要判断浏览器是否支持worker对象,详见如下代码.或者浏览器是否支持indexedDB数据库,详见同下,二者判断最好选择前者.因为IE不支持indexedDB . if(window.Worker){ dosometh

  • JavaScript中localStorage对象存储方式实例分析

    本文实例讲述了JavaScript中localStorage对象存储方式.分享给大家供大家参考,具体如下: [Local storage limitations]文章中提及JavaScript里的local storge的限制,例子中在localStorage里存储了一个bool型的数据,但是却没有像我们期待的一样进行存储. 当我们存储布尔型,数值型,字符串型时,localStorage对象会将我们存储的数据默认转为字符串字面量. localStorage[0] = false;// "fals

随机推荐