广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >JavaScript事件循环剖析宏任务与微任务
  • 733
分享到

JavaScript事件循环剖析宏任务与微任务

JavaScript 事件循环宏任务微任务JavaScript 事件循环 2022-11-13 18:11:43 733人浏览 薄情痞子
摘要

目录前言引言为什么会有事件循环?js是单线程的同步任务和异步任务 JS事件循环宏任务与微任务常见的宏任务有哪些?常见的微任务有哪些?执行过程总结(重点)同步任务 &mdas

前言

相信对于刚学习javascript的新手来说,去理解JS中的事件循环原理以及异步执行过程比较困难,但是这是JS必须要会的基础知识,逃避不能解决问题,笔者曾经也被这个知识点困扰过,现根据以往的经验编写此文章,旨在帮助大家彻底搞懂它们以及自我巩固,话不多说,进入正题。

注意:本篇文章主要是基于浏览器环境,node环境没有研究过暂不讨论

引言

我们先来小试牛刀,看看下面这段代码是怎么执行的,例1:

  setTimeout(() => {
    console.log('time')
  });
  new Promise((resolve, reject) => {
    console.log('p1');
    resolve();
  }).then(() => {
    console.log('res')
  });
  console.log(1);
 // 输出: p1 1 res time

怎么样?你想的输出结果和实际的输出结果是一样的吗?如果是一样的说明你对事件循环有一定的了解,但是你真的已经清楚的知道了事件循环的原理吗?让我们继续往下看。

为什么会有事件循环?

JS是单线程的

众所周知:JavaScript 是一门单线程语言,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚 本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对 某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉

为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 WEB Worker 标准,允许JavaScript 脚本创建多个线程,但是子线程完全受主线程控制。于是,JS 中出现了同步任务和异步任务。

同步任务和异步任务 

  • 同步任务:

同步任务都在主线程上执行,形成一个执行栈。在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

  • 异步任务:

不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。JS 的异步是通过回调函数实现的。异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列

注意:异步任务执行机制在这里描述的比较笼统,主要方便大家理解,具体细节在后面的“宏任务与微任务”中会详细介绍

JS的事件循环就是基于同步任务与异步任务来展开的,让我们继续往下看:

JS事件循环

事件循环是JavaScript实现异步的一种方法,也是JavaScript的执行机制

如图:

当一个脚本第一次执行的时候,js引擎会解析这段代码,并将其中的同步代码按照执行顺序加入执行栈中,然后从头开始执行。

当遇到异步任务时不会一直等待事件的返回结果,而是将事件挂起(即交给其他线程处理,上图是指Web Worker),继续执行执行栈中的其他任务。

当异步事件返回结果时,js将异步事件callback函数放入队列中,被放入队列中的异步事件不会立即回调,等到当前执行栈中的任务都执行完成,处于闲置状态的主线程按照队列顺序将处于首位事件的callback函数放入执行栈中,执行该函数的同步代码,如果遇到了异步事件,同样也会将其回调函数放入事件队列中…

如此反复,就形成了一个循环,这也是被称为“事件循环(EventLoop)”的原因。

js事件循环的基本原理已经描述清楚,但是异步任务之间也有所不同:

任务队列实际上分为两个:宏任务队列和微任务队列。上图只表示了一个是为了便于大家理解事件循环,下面就是事件循环更细节的东西了

宏任务与微任务

上面讲到,js在执行异步任务时,回调函数会被放在js的任务队列中,实际上,回调函数的类别不同,执行的优先级也不同。

不同的优先级被分为两类,一类是宏任务(Micro task),一类是微任务(Macro task)。

回调函数是微任务时,会被放在微任务队列,回调函数是宏任务时,会被放在宏任务队列。

微任务的优先级高于宏任务,当主线程的任务执行完成时,会首先去执行微任务队列中首位的回调函数,当微任务队列中为空时,才回去执行宏任务队列中的回调函数。

常见的宏任务有哪些?

  • 包括整体代码 script
  • setTimeout()
  • setInterval()
  • setImmediate()(Node独有)
  • I/O
  • UI 交互事件(浏览器独有)
  • requestAnimationFrame() (浏览器独有)

常见的微任务有哪些?

  • Promise.then(); Promise.cath()
  • async/await
  • process.nextTick() (Node独有)
  • MutationObserver() (H5新增,监听DOM树变化)
  • Object.observe() (异步监视对象修改,已废弃)

注意:new Promise()属于同步任务,但是Promise.then(); Promise.cath()属于异步任务的微任务

执行过程总结(重点)

现在我们对事件循环有了深入了解了,但是它们的执行过程还不是很清晰,我们再把执行过程弄清楚了以后就能游刃有余了。

同步任务 —> 微任务 —> 宏任务...

  • 先执行所有同步任务,碰到异步任务放到任务队列中
  • 同步任务执行完毕,开始执行当前所有的异步任务
  • 先执行任务队列里面所有的微任务,如果执行过程中又产生了微任务也会在本次执行过程中执行(即在下一个宏任务执行之前执行,可以看看案例1)
  • 然后执行一个宏任务(从宏任务队列头部pop出一个宏任务进执行栈,该任务中的具体代码也如步骤1执行)
  • 然后再执行所有的微任务(此时的微任务一般为步骤4中产生出的微任务)
  • 再执行一个宏任务,再执行所有的微任务·······依次类推到执行结束。

3-6的这个循环称为事件循环Event Loop

案例挑战

学会了吗?让我们来做几个案例巩固一下吧

案例1:

const promise = new Promise((resolve, reject) => {
    resolve("10")
  }).then(res => {
    console.log("res1:", res)    //res1: hahaha
    return 9
  }).then(res => {
    console.log("res2:", res)    //res2: 9
    return 8
  }).then(res => {
    console.log("res3:", res)    //res3: 8
    let promise2=new Promise((resolve,reject)=>{
        resolve("p2")
      }).then(res=>{
        console.log(res)
        setTimeout(function(){
          console.log("setTimeout2")
        },0)
      })
  })
  console.log('aaa')
  setTimeout(function(){
    console.log("setTimeout1")
  },0)
  const promise1 = new Promise((resolve, reject) => {
    console.log("p1")
    resolve(989)
}).then(res => {
    console.log(res)
    return 990
}).then(res=>{
  console.log(res)
  return 991
}).then(res=>{
  console.log(res)
  return 0
})

案例2:

console.log('1');
// 定义注解 setTimeout_1 用于下文使用方便
setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})
// setTimeout_2
setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})
// 输出结果:  1 7 6 8 2 4 3 5 9 11 10 12

案例3:

console.log('1');    
setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})
setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})
// 输出结果:1 7 6 8 2 4 3 5 9 11 10 12

以上就是JavaScript事件循环剖析宏任务与微任务的详细内容,更多关于JavaScript 事件循环宏任务微任务的资料请关注编程网其它相关文章!

--结束END--

本文标题: JavaScript事件循环剖析宏任务与微任务

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

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

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

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

下载Word文档
猜你喜欢
  • JavaScript事件循环剖析宏任务与微任务
    目录前言引言为什么会有事件循环?JS是单线程的同步任务和异步任务 JS事件循环宏任务与微任务常见的宏任务有哪些?常见的微任务有哪些?执行过程总结(重点)同步任务 &mdas...
    99+
    2022-11-13
    JavaScript 事件循环宏任务微任务 JavaScript 事件循环
  • JavaScript 事件循环中微任务和宏任务有什么区别
    JavaScript 事件循环中微任务和宏任务有什么区别,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。事件循环:微任务和宏任务浏览器中 Jav...
    99+
    2022-10-19
  • 详解JS事件循环及宏任务微任务的原理
    目录宏任务微任务事件循环宏任务与微任务微任务中创建宏任务宏任务中创建微任务宏任务中创建宏任务微任务中创建微任务总结本质上来说,JavaScript是同步的、阻塞的、单线程语言,不管是...
    99+
    2022-11-13
  • JavaScript 操作宏任务与微任务
    宏任务与微任务 javaScript是单线程语言(如果多线程dom会疯掉) 所以在同一时间只能执行一个任务,称为主线程,用来执行同步任务 同时还有两个任务列...
    99+
    2022-11-12
  • JavaScript事件循环同步任务与异步任务
    目录前言执行栈与任务队列执行栈任务队列同步任务与异步任务同步任务异步任务js的执行机制结语前言 首先,在学习js中同步异步的问题前,需要明白,js是单线程的,为什么它得是单线程的呢?...
    99+
    2022-11-13
  • JavaScript事件循环同步任务与异步任务实例分析
    本篇内容介绍了“JavaScript事件循环同步任务与异步任务实例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!执行栈与任务队列执行栈姑...
    99+
    2023-07-02
  • JavaScript事件循环同步任务与异步任务怎么实现
    这篇文章主要介绍“JavaScript事件循环同步任务与异步任务怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JavaScript事件循环同步任务与异步任务...
    99+
    2022-10-19
  • 如何进行JavaScript微任务和宏任务的分析
    这篇文章将为大家详细讲解有关如何进行JavaScript微任务和宏任务的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。前言:js是一门单线程语言,所以它本身是不可能异步的,但是js的宿主...
    99+
    2023-06-22
  • 如何理解JavaScript 事件循环中的微任务Microtask
    如何理解JavaScript 事件循环中的微任务Microtask,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。微任务(Microtask)P...
    99+
    2022-10-19
  • 深入浅析Node事件循环中的微任务队列
    让我们继续进行第二个实验。实验二代码// index.js Promise.resolve().then(() => console.log("this is Promise.resolve 1")); proce...
    99+
    2023-05-14
    JavaScript Node.js 前端
  • Node事件循环中的微任务队列是什么
    这篇文章主要介绍“Node事件循环中的微任务队列是什么”,在日常操作中,相信很多人在Node事件循环中的微任务队列是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node事件循环中的微任务队列是什么”的疑...
    99+
    2023-07-06
  • mysql的计划任务与事件调度实例分析
    本文实例讲述了mysql的计划任务与事件调度。分享给大家供大家参考,具体如下: mysql事件是基于预定义的时间表运行的任务,因此有时它被称为预定事件。mysql事件也被称为“时间触发”,因为它是由时间触发...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作