js event loop事件队列详解(浏览器中)

简介: js event loop事件队列详解(浏览器中)

目录


前言

js是单线程的

认识一个栈两个队列

执行过程

异步任务怎么分配

简单例子

难一点的例子


前言



以下内容是js在浏览器中的事件队列执行,与在nodejs中有所区别,请注意。


js是单线程的



要知道js是单线程的,就是一件一件做,做完一件做下一件。


认识一个栈两个队列



一个调用栈Stack。

一个宏队列,macrotask,也叫tasks。

一个微队列,microtask,也叫jobs。


执行过程



js就是执行全局Script同步代码,这中间碰到一些异步任务先加进对应的队列。


做完之后,调用栈就为空了。


然后将队列(先微队列后宏队列)里面的首个任务提到调用栈来做,一件一件做完直到队列中的任务都做完。


总结就是,先做同步的任务,再做微队列的任务,再做宏队列的任务。


异步任务怎么分配



这些异步任务包括但不限于:


以下分配给宏队列:


setTimeout

setInterval

requestAnimationFrame

I/O

UI rendering

以下分配给微队列:


Promise

Object.observe

MutationObserver

常见的宏队列:setTimeout,常见的微队列:Promise。


简单例子


    console.log("同步任务1");
    setTimeout(() => {
      console.log("宏任务");
    });
    new Promise((resolve, reject) => {
      console.log("同步任务2");
      resolve("微任务");
    }).then((data) => {
      console.log(data);
    });
    console.log("同步任务3");

结果是(按标号加任务,按箭头执行):

image.png

image.png

需要注意的是Promise的第一层没有执行回调之前是同步的,也就是上面的同步任务2。

难一点的例子


    console.log("同步任务1");
    console.log("同步任务2");
    new Promise((resolve, reject) => {
      console.log("同步任务3");
      setTimeout(() => {
        console.log("宏任务1");
        Promise.resolve()
          .then(() => {
            console.log("微任务5");
          })
          .then(() => {
            console.log("微任务6");
          });
      });
      resolve("微任务1");
    })
      .then((data) => {
        console.log(data);
        return "微任务3";
      })
      .then((data) => {
        console.log(data);
      });
    setTimeout(() => {
      console.log("宏任务2");
    }, 0);
    new Promise((resolve, reject) => {
      resolve("微任务2");
    })
      .then((data, resolve) => {
        console.log(data);
        return "微任务4";
      })
      .then((data) => {
        console.log(data);
      });
    console.log("同步任务4");

如何看呢,先看第一层,红色代表同步,绿色微任务,蓝色宏任务。

我们会把同步任务执行完,然后看见微任务有俩,宏任务也有俩。

本来的执行顺序可能是这样(我这里按照序号来表达顺序了,请和简单例子区分开来):

image.png

但是没那么顺利,执行到标号6时不一样了。


因为微任务执行过程中可能会产生新的微任务。


上面的微任务1执行完会把微任务3加在微任务2后面,也就是微任务2执行完也轮不到宏任务,会继续执行新的微任务直到微任务队列暂时为空。


所以接下来会按照加入队列的顺序执行完四个微任务,这时候发现没有新的微任务产生,才开始执行宏任务

image.png

但是需要注意的是,上面执行到标号5时又不一样了,宏任务一执行后又产生了新的微任务,所以宏任务两个并没有顺利连续执行,而是被插入的微任务拦住了。

(要记住微任务与宏任务队列都存在时一定是微任务先执行完再来执行宏任务,即使是宏任务执行产生的微任务也同理)

image.png

所以最后的答案,如果存在不理解的,可以在认真回顾一下上文:

image.png

相关文章
|
8天前
|
JavaScript 前端开发 API
详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务
该文章详细讲解了队列数据结构在前端开发中的应用,并深入探讨了JavaScript的事件循环机制,区分了宏任务和微任务的执行顺序及其对前端性能的影响。
|
8天前
|
Web App开发 JavaScript 前端开发
添加浮动按钮点击滚动到网页底部的纯JavaScript演示代码 IE9、11,Maxthon 1.6.7,Firefox30、31,360极速浏览器7.5.3.308下测试正常
添加浮动按钮点击滚动到网页底部的纯JavaScript演示代码 IE9、11,Maxthon 1.6.7,Firefox30、31,360极速浏览器7.5.3.308下测试正常
|
9天前
|
JavaScript 前端开发
JavaScript HTML DOM 事件
JavaScript HTML DOM 事件
14 5
|
9天前
|
监控 JavaScript 前端开发
|
9天前
|
JavaScript 前端开发
js之浏览器对象|28
js之浏览器对象|28
|
27天前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
这篇文章介绍了在Nest.js构建应用时,如何通过事件/发布-订阅模式使应用程序更健壮、灵活、易于扩展,并简化服务间通信。文章主要围绕@nestjs/event-emitter模块展开,这是一个基于eventemitter2库的社区模块,提供了事件发布/订阅功能,使得实现事件驱动架构变得简单。文章还介绍了如何使用该模块,包括安装依赖、初始化模块、注册EventEmitterModule、使用装饰器简化监听等。最后总结,集成@nestjs/event-emitter模块可以提升应用程序的事件驱动能力,构建出更为松耦合、易扩展且高度灵活的系统架构,是构建现代、响应迅速且具有高度解耦特性的Nest.
|
22天前
|
JavaScript 前端开发
|
2月前
|
机器学习/深度学习 人工智能 前端开发
【人工智能】利用TensorFlow.js在浏览器中实现一个基本的情感分析系统
使用TensorFlow.js在浏览器中进行情感分析是一个非常实用的应用场景。TensorFlow.js 是一个用于在JavaScript环境中训练和部署机器学习模型的库,使得开发者能够在客户端直接运行复杂的机器学习任务。对于情感分析,我们可以使用预先训练好的模型来识别文本中的积极、消极或中性情感。
65 4
【人工智能】利用TensorFlow.js在浏览器中实现一个基本的情感分析系统
|
2月前
|
机器学习/深度学习 存储 前端开发
实战揭秘:如何借助TensorFlow.js的强大力量,轻松将高效能的机器学习模型无缝集成到Web浏览器中,从而打造智能化的前端应用并优化用户体验
【8月更文挑战第31天】将机器学习模型集成到Web应用中,可让用户在浏览器内体验智能化功能。TensorFlow.js作为在客户端浏览器中运行的库,提供了强大支持。本文通过问答形式详细介绍如何使用TensorFlow.js将机器学习模型带入Web浏览器,并通过具体示例代码展示最佳实践。首先,需在HTML文件中引入TensorFlow.js库;接着,可通过加载预训练模型如MobileNet实现图像分类;然后,编写代码处理图像识别并显示结果;此外,还介绍了如何训练自定义模型及优化模型性能的方法,包括模型量化、剪枝和压缩等。
34 1
|
2月前
|
编解码 JavaScript 前端开发
JS逆向浏览器脱环境专题:事件学习和编写、DOM和BOM结构、指纹验证排查、代理自吐环境通杀环境检测、脱环境框架、脱环境插件解决
JS逆向浏览器脱环境专题:事件学习和编写、DOM和BOM结构、指纹验证排查、代理自吐环境通杀环境检测、脱环境框架、脱环境插件解决
58 1
下一篇
无影云桌面