iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >一文详解JS中的事件循环机制
  • 471
分享到

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

2024-04-02 19:04:59 471人浏览 泡泡鱼
摘要

目录前言1、javascript是单线程的2、同步和异步3、事件循环前言 我们知道JavaScript 是单线程的编程语言,只能同一时间内做一件事,按顺序来处理事件,但是在遇到异步事

前言

我们知道JavaScript 是单线程的编程语言,只能同一时间内做一件事,按顺序来处理事件,但是在遇到异步事件的时候,js线程并没有阻塞,还会继续执行,这又是为什么呢?本文来总结一下js 的事件循环机制。

1、JavaScript是单线程的

JavaScript 是一种单线程的编程语言,只有一个调用栈,决定了它在同一时间只能做一件事。在代码执行的时候,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行。在执行同步代码的时候,如果遇到了异步事件,js 引擎并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。因此JS又是一个非阻塞、异步、并发式的编程语言。

2、同步和异步

同步和异步的关系就类似于我们在餐厅排队吃饭的时候,每个人必须挨个的排队来进行买饭这个操作,而在这个过程中十分无聊,这时候我们可以边排着队边玩下手机,不需多久就排到了我们买饭。这个排队过程就是JS中的一个同步操作,玩手机就像一个异步操作。同步和异步的差别就在于排队买饭和玩手机这两个任务的执行顺序的不同。

同步: 指的是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是处于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。

异步: 指的是不进入主线程,某个异步任务可以执行了,该任务才会进入主线程执行。执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

console.log(1);
setTimeout(() => {
  console.log(2);
}, 0);
setTimeout(() => {
  console.log(3);
}, 0);
setTimeout(() => {
  console.log(4);
}, 0);
console.log(5);

上面的代码会打印  1 》 5 》 2 》 3 》4,为什么会产生这样的结果,我们来看下事件循环。

3、事件循环

事件循环过程可以简单描述为:

a、函数入栈,当 Stack 中执行到异步任务的时候,就将他丢给 webapis ,接着执行同步任务,直到 Stack 为空;

b、在此期间 WEBapis 完成这个事件,把回调函数放入 CallbackQueue (任务队列)中等待;

c、当执行栈为空时,Event Loop 把 Callback Queue中的一个任务放入Stack中,回到第1步。

事件循环(Event Loop) 是让 JavaScript 做到既是单线程,又绝对不会阻塞的核心机制,也是 JavaScript 并发模型(Concurrency Model)的基础,是用来协调各种事件、用户交互、脚本执行、UI 渲染、网络请求等的一种机制。在执行和协调各种任务时,Event Loop 会维护自己的事件队列。

事件队列是一个存储着待执行任务的队列,其中的任务严格按照时间先后顺序执行,排在队头的任务将会率先执行,而排在队尾的任务会最后执行。事件队列每次仅执行一个任务,在该任务执行完毕之后,再执行下一个任务,一个任务开始后直至结束,不会被其他任务中断。执行栈则是一个类似于函数调用栈的运行容器,当执行栈为空时,JS 引擎便检查事件队列,如果不为空的话,事件队列便将第一个任务压入执行栈中运行。

任务队列:在JavaScript中,异步任务被分为两种,一种宏任务(MacroTask)也叫Task,一种叫微任务:

宏任务的例子很多,包括创建主文档对象、解析html、执行主线(或全局)JavaScript代码,更改当前URL以及各种事件,如页面加载、输入、网络事件和定时器事件。从浏览器的角度来看,宏任务代表一个个离散的、独立工作单元。运行完任务后,浏览器可以继续其他调度,如重新渲染页面的UI或执行垃圾回收。

而微任务是更小的任务。微任务更新应用程序的状态,但必须在浏览器任务继续执行其他任务之前执行,浏览器任务包括重新渲染页面的UI。微任务的案例包括promise回调函数、DOM发生变化等。微任务需要尽可能快地、通过异步方式执行,同时不能产生全新的微任务。微任务使得我们能够在重新渲染UI之前执行指定的行为,避免不必要的UI重绘,UI重绘会使应用程序的状态不连续。

当当前执行栈中的事件执行完毕后,js 引擎首先会判断微任务对列中是否有任务可以执行,如果有就将微任务队首的事件压入栈中执行。当微任务对列中的任务都执行完成后再去判断宏任务对列中的任务。每次宏任务执行完毕,都会去判断微任务队列是否产生新任务,若存在就优先执行微任务,否则按序执行宏任务。

事件循环通常至少需要两个任务队列:宏任务队列和微任务队列。两种队列在同一时刻都只执行一个任务。

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");

按照上面的内容,分析执行步骤:

1、宏任务:执行整体代码(相当于<script>中的代码):

  • 输出: script start
  • 遇到 setTimeout,加入宏任务队列,当前宏任务队列(setTimeout)
  • 遇到 promise,加入微任务,当前微任务队列(promise1)
  • 输出:script end

2、微任务:执行微任务队列(promise1)

  • 输出:promise1,then 之后产生一个微任务,加入微任务队列,当前微任务队列(promise2)
  • 执行 then,输出promise2
  • 执行渲染操作,更新界面。
  • 宏任务:执行 setTimeout
  • 输出:setTimeout

注意: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");

步骤解析:

当前任务队列:微任务: [], 宏任务:[<script>]

宏任务:

  • 输出: script start
  • 遇到 timeout1,加入宏任务
  • 遇到 Promise,输出promise1,直接 resolve,将 then 加入微任务,遇到 timeout2,加入宏任务。
  • 输出script end
  • 宏任务第一个执行结束
  • 当前任务队列:微任务[then1],宏任务[timeou1, timeout2]

微任务:

  • 执行 then1,输出then1
  • 微任务队列清空
  • 当前任务队列:微任务[],宏任务[timeou1, timeout2]

宏任务:

  • 输出timeout1
  • 输出timeout2
  • 当前任务队列:微任务[],宏任务[timeou2]

微任务:

  • 为空跳过
  • 当前任务队列:微任务[],宏任务[timeou2]

宏任务:

输出timeout2

注意:async 和 await 其实就是 Generator 和 Promise 的语法糖。async 函数和普通 函数没有什么不同,他只是表示这个函数里有异步操作的方法,并返回一个 Promise 对象

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");

步骤解析:

当前任务队列:宏任务:[<script>],微任务: []

宏任务:

  • 输出:async1 start
  • 遇到 async2,输出:async2,并将 then(async1 end)加入微任务
  • 遇到 setTimeout,加入宏任务。
  • 遇到 Promise,输出:promise1,直接 resolve,将 then(promise2)加入微任务
  • 输出:script end
  • 当前任务队列:微任务[promise2, async1 end],宏任务[timeout]

微任务:

  • 输出:promise2
  • promise2 出队
  • 输出:async1 end
  • async1 end 出队
  • 微任务队列清空
  • 当前任务队列:微任务[],宏任务[timeout]

宏任务:

  • 输出:timeout
  • timeout 出队,宏任务清空

到此这篇关于一文详解JS中的事件循环机制的文章就介绍到这了,更多相关JS事件循环机制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 一文详解JS中的事件循环机制

本文链接: https://www.lsjlt.com/news/144554.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一文详解JS中的事件循环机制
    目录前言1、JavaScript是单线程的2、同步和异步3、事件循环前言 我们知道JavaScript 是单线程的编程语言,只能同一时间内做一件事,按顺序来处理事件,但是在遇到异步事...
    99+
    2024-04-02
  • 实例详解JS中的事件循环机制
    目录一、前言二、宏、微任务三、Tick 执行顺序四、案例详解1.掺杂setTimeout2.掺杂微任务,此处主要是Promise.then3.掺杂async/await一、前言 之前...
    99+
    2024-04-02
  • JS的事件循环执行机制详解
    目录前言JS语言的特点JS中同步和异步的使用事件循环是什么?事件循环执行过程微任务和宏任务的区别JS执行/运行机制最后前言 在前端开发中,涉及到JS原生的使用原理是非常重要的知识点,...
    99+
    2023-05-19
    JS事件循环执行机制 JS事件循环 JS事件
  • node.js事件循环机制及与js区别详解
    目录一、是什么二、流程三、题目一、是什么 在浏览器事件循环(opens new window)中,我们了解到javascript在浏览器中的事件循环机制,其是根据HTML5定义的规范...
    99+
    2024-04-02
  • JS中事件循环机制的示例分析
    小编给大家分享一下JS中事件循环机制的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1、JavaScript是单线程的JavaScript 是一种单线程的...
    99+
    2023-06-29
  • 关于js的事件循环机制剖析
    前言 众所周知, JavaScript是单线程这一核心,可是浏览器又能很好的处理异步请求,那么到底是为什么呢?其中的原理与事件循环机制大有关系。 在探索事件循环之前,我们得先了解浏览...
    99+
    2024-04-02
  • 一篇文章带你了解vue.js的事件循环机制
    目录一、事件循环机制介绍       二、经典事件循环面试题总结一、事件循环机制介绍    ...
    99+
    2024-04-02
  • Javascript前端事件循环机制详细讲解
    目录一、消息队列和事件循环1.单线程处理机制2.事件循环机制3.消息队列4.IO线程5.页面使用单线程的缺点二、setTimeout1.浏览器怎么实现 setTimeout2.使用s...
    99+
    2022-12-30
    JavaScript事件循环机制 JS循环机制
  • JS中浏览器事件循环机制的示例分析
    这篇文章将为大家详细讲解有关JS中浏览器事件循环机制的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。先来明白些概念性内容。进程、线程进程是系统分配的独立资源,是 ...
    99+
    2024-04-02
  • vue.js的事件循环机制如何理解
    这篇文章主要介绍了vue.js的事件循环机制如何理解的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue.js的事件循环机制如何理解文章都会有所收获,下面我们一起来看看吧。一、事件循环机制介绍  &n...
    99+
    2023-06-29
  • 深入了解Javascript的事件循环机制
    目录单线程的Javascript同步 vs 异步 宏任务 vs 微任务定时器To Be Continued单线程的Javascript JavaScript是一种单线程语言,它主要用...
    99+
    2024-04-02
  • Node.js中事件循环的机制是什么
    本篇内容介绍了“Node.js中事件循环的机制是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!先看一个demo:setTimeout((...
    99+
    2023-06-17
  • 详解JavaScript事件循环
    目录一、事件循环的执行过程二、事件循环进阶用法三、JavaScript任务类型3.1 同步任务&异步任务3.2 宏任务&微任务JavaScript事件循环是一种机制,...
    99+
    2023-05-16
    JavaScript事件循环 JavaScript循环
  • 深入了解Node事件循环(EventLoop)机制
    主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。下面本篇文章就来带大家掌握Node.js中的eventloop,希望对大家有所帮助!虽然js可以在浏览器...
    99+
    2023-05-14
    javascript Node.js 面试 前端
  • nodejs中事件循环机制的示例分析
    这篇文章主要介绍了nodejs中事件循环机制的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前端开发离不开JavaScript,Javascript是一种web前端语...
    99+
    2023-06-14
  • Node.js 事件循环的原理与机制
    ...
    99+
    2024-04-02
  • 一文搞懂Node的的事件循环
    本篇文章聊聊Nodejs中的事件循环,希望带大家搞懂Nodejs中的事件循环,从此再也不怕面试官的灵魂发问:谈一下Nodejs的事件循环!想必大家面试的时候,都会被面试官问道:“谈谈Nodejs的事件循环吧”。因为本人也被问道过,但每一次都...
    99+
    2023-05-14
    后端 Node.js
  • Node事件循环机制是什么
    这篇文章主要介绍“Node事件循环机制是什么”,在日常操作中,相信很多人在Node事件循环机制是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node事件循环机制是什么”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-07-05
  • 一文带你搞懂面试率超高的JS事件循环
    目录1. 异步执行原理(1)单线程的JavaScript(2)多线程的浏览器2. 浏览器事件循环(1)执行栈与任务队列(2)宏任务和微任务3. Node.js的事件循环(1)事件循环...
    99+
    2022-11-13
    JS 事件循环
  • JS面试之对事件循环的理解
    目录一、是什么事件循环(Event Loop)二、宏任务与微任务微任务宏任务三、async与awaitasyncawait四、流程分析 一、是什么 JavaScript 在...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作