资讯专栏INFORMATION COLUMN

JavaScript事件循环探索

hqman / 2575人阅读

摘要:事件循环事件循环具有至少两个队列处理任务。同时含有宏任务和微任务主线程运行运行运行运行本例中在的事件处理函数里增加了一个立即兑现的,需要运行。处理的事件处理函数计时器主线程运行运行运行运行

一直对js的事件循环不是很清晰,最近看了JavaScript忍者秘籍的第13章后,有了一些感悟,特此总结一下,分享给大家。

单线程

众所周知,JavaScript是单线程执行模型,同一时刻只能执行一个代码片段,一个任务开始后知道运行完成,不会被其他任务中断。当一个任务花费的时间很长的话,用户就会明显的感觉到卡顿。浏览器为了解决这个问题引入了事件循环的概念(Event Loop)。

事件循环

事件循环具有至少两个队列处理任务。任务分为两类,宏任务(macro-task)和微任务(micro-task)。

1.宏任务代表一个个离散、独立的工作单元,运行完之后,浏览器可以继续其他的调度。包括:创建文档对象,解析HTML,执行JavaScript,以及各种事件……
2.微任务是更小的任务,主要用户更新应用程序的状态,必须在浏览器任务继续执行其他任务之前执行。微任务需要尽可能快地通过异步方式执行,同时不能产生全新的微任务。包括promise、回调函数、DOM发生变化……
仅包含宏任务
// 主线程JavaScript运行15ms
btn1.addEventListener("click", function() {运行 8ms}, false);
btn2.addEventListener("click", function() {运行 5ms}, false);

现在假设主线程运行15ms, 在第5ms单击btn1,在第12ms的时候单击btn2。基于单线程执行模型,单击按钮之后不会立即执行对应的处理函数,因为一个任务一旦开始就不会被另一个任务中断。因此,在主线程执行的15ms期间,按钮的单击处理函数放入队列。当主线程执行完成也就是15ms之后,程序开始处理微任务,因为当前不存在微任务,跳过此步骤,开始执行更新UI。

之后进入第二次循环,也就是开始执行btn1的处理函数,需要运行8ms,btn2处理函数在队列中等待。当btn1处理函数执行完之后,浏览器检查微任务是否存在和是否更新UI,删除任务队列里的btn1的处理函数。

最后进入第三次循环,开始执行btn2的处理函数,需要运行5ms,处理函数执行完之后,检查微任务和是否需要更新UI,删除任务队列里的btn2的处理函数,最终任务队列为空,循环结束。

同时含有宏任务和微任务
// 主线程JavaScript运行15ms
btn1.addEventListener("click", function() {
    Promise.resolve().then(() => {
       运行 4ms 
    });
    运行 8ms 
}, false);
btn2.addEventListener("click", function() {运行 5ms}, false);

本例中在btn1的事件处理函数里增加了一个立即兑现的Promise,需要运行4ms。

现在代码的执行顺序为:

主线程执行15ms,在5ms和12ms的时候分别将处理函数放入任务队列,更新UI。

15m后处理btn1事件处理函数,发现Promise,放入微任务队列,btn1事件处理函数继续执行8ms,检查微任务队列发现有Promise回调函数,然后开始执行Promise回调函数,运行4ms,继续检查微任务队列,如果为空,检查是否需要更新UI,进入下一轮循环。

处理btn2的事件处理函数……

计时器
// 主线程JavaScript运行18ms
setTimeout(function() {
    运行6ms;
}, 10);
setInterval(function() {
    运行8ms;
}, 10);
btn1.addEventListener("click", function() {运行 10ms}, false);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96237.html

相关文章

  • 简洁明了探索浏览器Event loop

    摘要:前段时间我对于浏览器中的和哪个先执行有所困惑,苦于搜索也没有发现很明确的答案,于是决定深入探索浏览器,现有所愚见,想与大家分享,希望能帮助到那些还在爬坑的人。浏览器端中的异步队列有两种队列和队列。浏览器会不断从队列中按顺序取执行。 前段时间我对于浏览器Event loop中的MacroTask和MicroTask哪个先执行有所困惑,苦于搜索也没有发现很明确的答案,于是决定深入探索浏览器...

    DrizzleX 评论0 收藏0
  • JavaScript是如何工作的:Web Workers的构建块+ 5个使用他们的场景

    摘要:最后,提供个正确使用的场景。异步编程的一个很好的用例就请求。这意味着异步函数只能解决一小部分语言单线程中的局限性问题。中有类似的集群子进程概念,他们也是多线程但是和还是有区别。可用的特性由于的多线程特性,工作者只能访问特性的一个子集。 showImg(https://segmentfault.com/img/bVblS8J?w=400&h=298); 这是专门探索 JavaScript...

    ningwang 评论0 收藏0
  • JavaScript是如何工作: 深入探索 websocket 和HTTP/2与SSE +如何选择正

    摘要:数据作为消息通过传输,每个消息由一个或多个帧组成,其中包含正在发送的数据有效负载。帧数据如上所述,数据可以被分割成多个帧。但是,规范希望能够处理交错的控制帧。 文章底部分享给大家一套 react + socket 实战教程 这是专门探索 JavaScript 及其所构建的组件的系列文章的第5篇。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 如果你错过了前面的章...

    cuieney 评论0 收藏0
  • node核心特性理解

    摘要:概述本文主要介绍了我对的一些核心特性的理解,包括架构特点机制核心模块与简单应用。在此期间,主线程继续执行其他任务。延续了浏览器端单线程,只用一个主线程执行,不断循环遍历事件队列,执行事件。 原文地址在我的博客,转载请注明来源,谢谢! node是在前端领域经常看到的词。node对于前端的重要性已经不言而喻,掌握node也是作为合格的前端工程师一项基本功了。知道node、知道后端的一些东西...

    huangjinnan 评论0 收藏0
  • 学习JavaScript之内存泄漏

    摘要:接上回我写了一篇关于闭包的博客学习之闭包,最后谈到闭包导致的问题时留了一个尾在以下的浏览器中会有内存泄漏的问题。今天的博客就继续探索一下内存泄漏的问题。博客地址的前端之路原文链接学习之内存泄漏 接上回我写了一篇关于闭包的博客《学习JavaScript之闭包》, 最后谈到闭包导致的问题时留了一个尾: 在IE9以下的浏览器中会有内存泄漏的问题。 今天的博客就继续探索一下内存泄漏的问题。 浅...

    nodejh 评论0 收藏0

发表评论

0条评论

hqman

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<