JS中的事件循环机制(Event Loop)

news2025/2/3 19:01:10

JS中的事件循环机制(Event Loop)

javascript是单线程非阻塞的脚本语言

  • 单线程
    只有一个主线程来处理任务。
  • 非阻塞
    JS引擎执行异步任务时,不会一直等待返回结果,主线程会挂起(pending)这个任务,继续执行其他任务,当异步任务返回结果时,js将异步任务的callback放到任务队列中,等到当前任务栈中的任务都执行完毕,处于闲置状态的主线程按照队列顺序将队首的calback函数加入到执行栈中,执行该函数的同步代码,如果又遇到异步任务,再将其回调函数加入到队列中–事件循环机制
    JS通常是非阻塞的,除了某些特殊情况,JS会停止代码执行:alert, confirm, prompt

js的任务队列分为同步任务异步任务

  • 同步任务
    在主线程里执行,当浏览器第一遍过滤html文件的时候可以执行完;(在当前作用域直接执行的所有内容,包括执行的方法、new出来的对象)

  • 异步任务
    比较耗费时间与性能的,当浏览器执行到这些的时候会将其丢到异步任务队列中,不会立即执行的任务

    异步任务分为宏任务(macrotask)微任务(microtask),执行的优先级不同

    宏任务:script, setTimeout, setInterval, setImmeditate, T/O, UI rendering
    微任务:process, nextTick, promise.then(), object.observe, MutationObserver, await, async

    回调函数是微任务,会被加入微任务队列,回调函数是宏任务,会被加入宏任务队列,微任务优先级高于宏任务

Event loop过程

  • 主线程开始执行一段代码, 假设开始执行一个 script 标签内的代码,将代码放入执行栈中执行,同步代码优先执行,执行过程中,当遇到任务源时,判断是宏任务还是微任务。
  • 如果是宏任务,加入到宏任务队列中,如果是微任务,加入到微任务队列中。
  • 同步代码执行完成,执行栈空闲,检查微任务队列中是否有可执行任务,如果有,依次执行所有微任务队列中的任务。如果没有。当前任务执行结束。
  • DOM渲染。
  • 检查宏任务队列是否有可执行的宏任务,如果有,取出队列中最前面的那个宏任务,加入到执行栈中开始执行,然后重复前面步骤,直到宏任务队列中所有任务执行结束

微任务在DOM渲染前触发,宏任务在DOM渲染后触发

代码示例1

// 语句一
console.log(1);
// 语句二
setTimeout(()=>{
    console.log(2);
},0);
//语句三
Promise.resolve().then(()=>{
    console.log(3);
})
// 语句四
console.log(4);

//输出顺序
//1,4,3,2

代码示例2

console.log("script start");
 
setTimeout(function () {
  console.log("setTimeout");
}, 0);
 
Promise.resolve()
  .then(function () {
    console.log("promise1");
  })
  .then(function () {
    console.log("promise2");
  });
 
console.log("script end");

代码示例3
new Promise(…)中的代码,也是同步代码,会立即执行。只有then之后的代码,才是异步执行的代码

console.log("script start");
 
setTimeout(function () {
  console.log("timeout1");
}, 10);
 
new Promise((resolve) => {
  console.log("promise1");
  resolve();
  setTimeout(() => console.log("timeout2"), 10);
}).then(function () {
  console.log("then1");
});
 
console.log("script end");

代码示例4
async 和 await 是 Generator 和 Promise 的语法糖。async 函数和普通函数一样,只是表示这个函数里有异步操作的方法,并返回一个 Promise 对象
await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。

// 等价
async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}
// Promise 写法
async function async1() {
  console.log("async1 start");
  Promise.resolve(async2()).then(() => console.log("async1 end"));
}
async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}
async function async2() {
  console.log("async2");
}
async1();
setTimeout(() => {
  console.log("timeout");
}, 0);
new Promise(function (resolve) {
  console.log("promise1");
  resolve();
}).then(function () {
  console.log("promise2");
});
console.log("script end");

代码示例5

const p = Promise.resolve();

(async () => {
    await p;
    console.log('await end');
})();

p.then(() => {
    console.log('then 1');
}).then(() => {
    console.log('then 2');
});

// 'then 1' => 'then 2' => 'await end'

代码示例6

// 1. 开始执行
console.log(1)     // 2. 打印 1

setTimeout(function () {    // 6. 浏览器在 0ms 后,将该函数推入任务队列
    console.log(2)    // 7. 打印 2
    Promise.resolve(1).then(function () {    // 8. 将 resolve(1) 推入任务队列  9. 将 function函数推入任务队列
        console.log('ok')    // 10. 打印 ok
    })
})    // 3.调用 setTimeout 函数,并定义其完成后执行的回调函数

setTimeout(function () {        // 11. 浏览器 0ms 后,将该函数推入任务队列
    console.log(3)    // 12. 打印 3
})    // 4. 调用 setTimeout 函数,并定义其完成后执行的回调函数

// 5. 主线程执行栈清空,开始读取 任务队列 中的任务

// output: 1  2 ok 3

代码示例7

setTimeout(function(){
  console.log('1')
});
 
new Promise(function(resolve){
  console.log('2');
  resolve();
}).then(function(){
  console.log('3')
});
 
var timer;
timer = setInterval(function(){
 console.log('5');
  clearInterval(timer);
});

new Promise(function(resolve){
  resolve();
}).then(function(){
  console.log('6')
});
console.log('4');

// 2,4,3,6,1,5

代码示例8

Promise.resolve().then(()=>{
  console.log('Promise1')  
  setTimeout(()=>{
    console.log('setTimeout2')
  },0)
});
setTimeout(()=>{
  console.log('setTimeout1')
  Promise.resolve().then(()=>{
    console.log('Promise2')    
  })
},0);
console.log('start');

// start -> Promise1 -> setTimeout1 -> Promise2 - > setTimeout2

实例

<body>
  <div id="box"></div>
  <script src="./app.js"></script>s
</body>

//js
const box = document.getElementById('box')
box.innerHTML = '<P>我是后来插进去的内容</P>'

console.log("1");

setTimeout( ()=>{
    console.log("2");
    alert("定时器执行了")
},0 )

Promise.resolve().then(()=>{
    console.log("3")
    alert("Promise执行了")
})

console.log("4");
  • tip:从规范来看,microtask (微任务)优先于 macrotask(宏任务) 执行,所以如果有需要优先执行的逻辑,放入microtask 队列会比 task 更早的被执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/103695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微三云(陈志坤):共享购商业模式概念、框架、基础制度

各位企业家及创业者朋友们&#xff0c;你们好。我是微三云&#xff08;陈志坤&#xff09;&#xff0c;在你打开这个文章的时候&#xff0c;先不要急&#xff0c;因为任何一个能够长久、安稳、盈利的平台&#xff0c;背后肯定有一位看准宏观方向且耐心的人。这是一个极具颠覆性…

php宝塔搭建部署实战零起飞OA办公管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的零起飞OA办公管理系统源码&#xff0c;感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板文字搭建教程 下载源码&#xff0c;宝…

Mybatis对MySQL中BLOB字段的读取

一、使用TEXT还是BLOB&#xff1f; 1、TEXT和BLOB主要差别 主要差别就是BLOB保存二进制数据&#xff0c;TEXT保存字符数据。 目前几乎博客内容里图片都不是二进制存储在数据库的&#xff0c;而是把图片上传到服务器&#xff0c;然后正文里使用<img>标签引用&#xff0c…

电脑系统下载的镜像文件在哪里图解

如果你在小白系统上面下载了镜像文件&#xff0c;但是不知道下载完成怎么找到它的话&#xff0c;下面就和小编一起来看一下小白系统下载的镜像文件知道方法。 工具/原料&#xff1a; 系统版本&#xff1a;windows10系统 品牌型号&#xff1a;惠普战66五代 方法/步骤&#x…

C/C++程序的断点调试 - Microsoft Visual Studio

本文以Microsoft Visual Studio为例&#xff0c;简述C/C程序断点调试的基本方法和过程。其它的IDE环境&#xff0c;大同小异。 本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载&#xff0c;但需要注明原作者"海洋饼干叔 叔"&#xff…

【BFS】八数码问题(c++基础算法)

目录 一.读题 二.在做题之前 1.康拓展开 2.DFS和BFS的区别 3.栈和队列的区别 三.做题 1.算法原理 2.算法实现 ①队列 ②康托展开 ③标记 四.AC代码 一.读题 作为最经典的一道宽度优先搜索题&#xff0c;它的题面并不是很难懂。 【宽搜&#xff08;难度&#xff1a;6&a…

爆款短视频拍摄技巧之摇、移、跟拍等,这样拍的视频才更有吸引力,速收藏

爆款短视频拍摄技巧之拍摄手法,这样拍的视频才更有吸引力。 拍摄技巧主要分为两个部分&#xff0c;一个是构图&#xff0c;一个是拍摄手法。上一篇我们聊过了两种构图手法&#xff0c;接下来咱们聊一下拍摄手法&#xff0c;也就是我们常说的推、拉、摇、移、跟这五种手法。 其…

NNDL 2022秋

第一届AI专业&#xff0c;很多课程都是第一次开课&#xff0c;老师和学生都在“摸着石头过河”。 好处是所学内容比较新&#xff0c;跟得上“潮流”&#xff0c;学习意愿比较强。 难处是教学资料相对欠缺&#xff0c;需要学的内容较多&#xff0c;难度较大。 大家经过一学期…

leetcode:1494. 并行课程 II【dfs记忆化 + 状态压缩】

目录题目截图题目分析ac code总结题目截图 题目分析 这道题很像toposort&#xff0c;但实际不是因为那些indeg为先为0的&#xff0c;先选不一定好的考虑到n很小我们使用状态压缩dfs(state)表示当前state下&#xff0c;还需要多少个学期结束用pre数组存一下每个idx对应的前置条…

基于C++11 实现的线程池

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 基于C11 实现的线程池基于C11 实现的线程池1、线程池原理2、线程池的设计思路&#xff1f;3、一个基于C11的优秀的线程池3.1 头文件3.2 线程池类3.3 构造函数实现3.4 入队—添…

ModStartBlog v6.4.0 升级输入过滤、多文件组件,修复已知问题

V6.4.0版本更新 2022年12月20日ModStartBlog发布v6.4.0版本&#xff0c;增加了以下14个特性&#xff1a; [新功能] 富文本过滤规则调整优化[新功能] ArrayPackage数组输入数据包处理器[新功能] 请求输入组件新增多文件路径类型[新功能] 多文件上传组件[新功能] 所有组件新增t…

RCE代码及命令执行(详解)

RCE代码及命令执行1.RCE漏洞1.1.漏洞原理1.2.漏洞产生条件1.3.漏洞挖掘1.4.漏洞分类1.4.1.命令执行1.4.1.1.漏洞原理1.4.1.2.命令执行危险函数1.4.1.3.漏洞检测1.4.2.代码执行1.4.2.1.漏洞原理1.4.2.2.代码执行危险函数1.4.2.3.漏洞检测1.5.命令执行和代码执行区别2.命令执行2.…

QT学习记录(二)最基础的工程

文件 工程新建后会有这几个文件&#xff0c;自动生成的 main.cpp #include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MainWindow w;w.show();return a.exec(); }QApplication a(argc, argv);这里…

Mentor-dft 学习笔记 day45-MTFI

Using MTFI Files此节介绍MTFI&#xff08;Mentor Tessend Fault Information&#xff09;功能&#xff0c;可用于ATPG工具和Tessent LogicBIST。MTFI是用于存储故障状态信息的通用且可扩展的文件格式。MTFI File Format MTFI是在“dft-edt”和“patterns-scan”上下文中读取和…

运用大O来给代码提速(冒泡排序)

本文内容借鉴一本我非常喜欢的书——《数据结构与算法图解》。学习之余&#xff0c;我决定把这本书精彩的部分摘录出来与大家分享。 本章内容 写在前面 1.冒泡排序 2.冒泡排序实战 3.冒泡排序的实现 4.冒泡排序的效率 5.二次问题 6.线性解决 7.总结 写在前面 大 O记…

Diffusion Model合集 part2

扩散模型原理介绍2五&#xff0c;逆扩散过程(Reverse Process)六&#xff0c;扩散过程中的后验的条件概率q(xt−1∣xt,x0)q(x_{t-1}|x_{t},x_{0})q(xt−1​∣xt​,x0​)七&#xff0c;目标数据分布的似然函数八&#xff0c;Diffusion Probabilistic Model的算法代码五&#xff…

“专利费用减缓”怎么申请?

在专利申请时&#xff0c;很多申请人对“专利费用减缓”的概念并不了解&#xff0c;或者不太清楚。甚至有很多申请人一听到专利申请可以请求费用减缓&#xff0c;就以为申请专利是不要钱的。当然&#xff0c;这样的理解就存在了很大的偏差了&#xff0c;所以&#xff0c;我们今…

Java Arrays类

JavaArrays类\huge{Java \space Arrays类}Java Arrays类 概述 Arrays类Arrays类Arrays类&#xff1a;本质就是一个工具类&#xff0c;用于操作数组元素的。 常用API ①. toString()&#xff08;重写过的toString方法&#xff09; toString()toString()toString()&#xff1a…

人才招聘网 招聘系统源码找工作源代码 各行业的招聘网站门户源码

运行环境&#xff1a;VS2015SqlServer2008R2.NET4.0 系统介绍&#xff1a; 适用于各地方或者各行业的招聘网站门户&#xff0c;相当强大的人才招聘网站&#xff0c;可登陆注册、支持第三方登陆&#xff0c;强大额后台管理&#xff0c;功能全面&#xff0c;界面美观 职位和简历…

如何用yolov5 训练自己的数据

文章目录 说明数据准备划分数据集转换数据label 格式训练前准备修改图片路径修改训练配置文件 voc.yaml修改 yolo配置文件开始训练没有GPU 或显存不够的说明 利用yolov5 训练自己的数据集通常需要利用自己标注的数据进行训练 接下来记录下如何训练自己的数据 数据准备 我这用的…