js在浏览器中的event loop事件队列示例详解

目录
  • 前言
  • 认识一个栈两个队列
  • 执行过程
  • 简单例子
  • 难一点的例子
  • 总结

前言

以下内容是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");

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

需要注意的是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");

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

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

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

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

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

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

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

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

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

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

总结

到此这篇关于js在浏览器中的event loop事件队列的文章就介绍到这了,更多相关js event loop事件队列内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JS事件循环机制event loop宏任务微任务原理解析

    首先看一段代码 async function (){ await f2() console.log('f1') } async function f2(){ console.log('f2') } console.log('正常1') f1() setTimeout(()=>{ console.log('定时器') }) console.log('正常2') 正确的打印顺序应该是:正常1,f2 ,正常2,f1,定时器 为什么会出现这样打印顺序呢 首先javascript是一门单线程语言,在最新的

  • JavaScript Event Loop相关原理解析

    1.单线程模型 单线程模型指的是,JavaScript只能在一个线程上运行,也就是说只能同时指向一个任务,其他任务都必须在后面排队等待.注意:虽然JavaScript只在一个线程上运行,但并不代码JavaScript引擎只有一个线程.事实上,JavaScript引擎有多个线程,单个脚本只能在一个线程上运行(主线程),其他线程都是在后台配合. JavaScript为什么要采用单线程,而不是多线程? 不想让浏览器变得复杂(避免复杂性),因为多线程需要共享资源.且可能修改彼此运行的结果. 该模式会导致

  • JavaScript运行机制之事件循环(Event Loop)详解

    一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. JavaScript的单线程,与它的用途有关.作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM.这决定了它只能是单线程,否则会带来很复杂的同步问题.比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线

  • 前端js中的事件循环eventloop机制详解

    前言 我们知道 js 是单线程执行的,那么异步的代码 js 是怎么处理的呢?例如下面的代码是如何进行输出的: console.log(1); setTimeout(function() { console.log(2); }, 0); new Promise(function(resolve) { console.log(3); resolve(Date.now()); }).then(function() { console.log(4); }); console.log(5); setTim

  • JavaScript中EventLoop介绍

    想象下,比如浏览器在运行一个复杂的图像转换算法,因为是单线程的,所以此时浏览器进程被阻塞了,不能进行界面渲染,也不能运行其他代码,你的应用界面会失去和用户的交互. 这一般情况下还不会有大问题,但是当浏览器在同时运行多个类似的算法时,这个问题就很严重了. 有一定经验js开发人员大多都理解代码的异步执行,特别是ajax的使用. // ajax(..) is some arbitrary Ajax function given by a library var response = ajax('htt

  • js在浏览器中的event loop事件队列示例详解

    目录 前言 认识一个栈两个队列 执行过程 简单例子 难一点的例子 总结 前言 以下内容是js在浏览器中的事件队列执行,与在nodejs中有所区别,请注意. 都说js是单线程的,不过它本身其实不是单线程,但是在浏览器中执行时只分配一个线程进行执行. 所以说js执行是单线程的,一次只能进行一项任务,就是一件任务一件任务做,做完一件做下一件. 认识一个栈两个队列 一个调用栈Stack. 一个宏队列,macrotask,也叫tasks. 一个微队列,microtask,也叫jobs. 执行过程 js就是

  • javascript中的event loop事件循环详解

    前言 javascript是单线程的语言,也就是说,同一个时间只能做一件事.而这个单线程的特性,与它的用途有关,作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM.这决定了它只能是单线程,否则会带来很复杂的同步问题.比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准? 为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是

  • vue+three.js实现炫酷的3D登陆页面示例详解

    目录 前言: Three.js的基础知识 关于场景 关于光源 关于相机(重要) 关于渲染器 完善效果 创建一个左上角的地球 使地球自转 创建星星 使星星运动 创建云以及运动轨迹 使云运动 完成three.js有关效果 结语 前言: 大家好,我是xx传媒严导(xx这两个字请自行脑补) . 该篇文章用到的主要技术:vue3.three.js 我们先看看成品效果: 高清大图预览(会有些慢): 座机小图预览: 废话不多说,直接进入正题 Three.js的基础知识 想象一下,在一个虚拟的3D世界中都需要什

  • Go语言中的字符串处理方法示例详解

    1 概述 字符串,string,一串固定长度的字符连接起来的字符集合.Go语言的字符串是使用UTF-8编码的.UTF-8是Unicode的实现方式之一. Go语言原生支持字符串.使用双引号("")或反引号(``)定义. 双引号:"", 用于单行字符串. 反引号:``,用于定义多行字符串,内部会原样解析. 示例: // 单行 "心有猛虎,细嗅蔷薇" // 多行 ` 大风歌 大风起兮云飞扬. 威加海内兮归故乡. 安得猛士兮守四方! ` 字符串支持转义

  • Go语言中循环语句使用的示例详解

    目录 一.概述 1. 循环控制语句 2. 无限循环 二.Go 语言 for 循环 1. 语法 2. for语句执行过程 3. 示例 4. For-each range 循环 三.循环嵌套 1. 语法 2. 示例 四.break 语句 1. 语法 2. 示例 五. continue 语句 1. 语法 2. 示例 六.goto 语句 1. 语法 2. 示例 一.概述 在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句. 循环程序的流程图: Go 语言提供了以下几种类型循环

  • RxJS中的Observable和Observer示例详解

    目录 引言 概念 牛刀小试 Observable Observable 剖析 Observer 结束语 引言 最近在项目当中别的小伙伴使用到了Rxjs,我一眼看上去有点懵,感觉挺复杂,挺绕的.于是抓紧补补课,然后就可以和小伙伴们一起交流怎么能优雅的使用Rxjs.由于内容比较多,会分为三篇来讲解说明 初识 RxJS中的 Observable 和 Observer 细说 RxJS中的 Operators 在谈 RxJS中的 Subject和Schedulers 概念 RxJS是一个库,可以使用可观察

  • JS前端二维数组生成树形结构示例详解

    目录 问题描述 实现步骤 完整代码 问题描述 前端在构建国家的省市区结构时,接口返回的不是树形结构,这个时候就需要我们进行转化.以下数据为例 [ [ { "districtId": 1586533852834, "parentCode": "000", "nodeCode": "000001", "name": "浙江省", "districtType&qu

  • flutter中使用流式布局示例详解

    目录 简介 Flow和FlowDelegate Flow的应用 总结 简介 我们在开发web应用的时候,有时候为了适应浏览器大小的调整,需要动态对页面的组件进行位置的调整.这时候就会用到flow layout,也就是流式布局. 同样的,在flutter中也有流式布局,这个流式布局的名字叫做Flow.事实上,在flutter中,Flow通常是和FlowDelegate一起使用的,FlowDelegate用来设置Flow子组件的大小和位置,通过使用FlowDelegate.paintChildre可

  • JS技巧动手实现红包兔子雨效果示例详解

    目录 前言 展示效果 技术栈 思考与实现 红包下落效果 生成红包雨 打开红包效果 兔子雨效果 拓展 设置中奖概率 后记 前言 人生天地之间,若白驹过隙,忽然而已.不知不觉中,2022年已然逝去,2023年也过去了半个月了.看到「兔了个兔」这个活动几天了,不过这周比较忙,没时间参与. 心血来潮,捣鼓了一晚上,实现一个兔年的红包雨(兔子雨)效果~ 展示效果 技术栈 Vue2 SCSS:实现红包雨(兔子雨)效果.按钮交互效果等. 思考与实现 首先,思考一下最终的展示效果:在屏幕上会有很多随机下落的兔子

  • C++中#include头文件的示例详解

    fstream是C++ STL中对文件操作的合集,包含了常用的所有文件操作.在C++中,所有的文件操作,都是以流(stream)的方式进行的,fstream也就是文件流file stream. 最常用的两种操作为: 1.插入器(<<) 向流输出数据.比如说打开了一个文件流fout,那么调用fout<<"Write to file"<<endl;就表示把字符串"Write to file"写入文件并换行. 2.析取器(>>

随机推荐