首页 > 编程语言 >JavaScript事件循环

JavaScript事件循环

时间:2023-01-19 01:55:21浏览次数:44  
标签:异步 console log JavaScript 任务 循环 Promise 事件 执行

一、是什么

先,JavaScript是一门单线程的语言,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环

JavaScript中,所有的任务都可以分为

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行

  • 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等

同步任务与异步任务的运行流程图如下:

从上面我们可以看到,同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就事件循环

二、宏任务与微任务

如果将任务划分为同步任务和异步任务并不是那么的准确,举个例子:

console.log(1)

setTimeout(()=>{
    console.log(2)
}, 0)

new Promise((resolve, reject)=>{
    console.log('new Promise')
    resolve()
}).then(()=>{
    console.log('then')
})

console.log(3)

如果按照上面流程图来分析代码,我们会得到下面的执行步骤:

  • console.log(1),同步任务,主线程中执行
  • setTimeout() ,异步任务,放到 Event Table,0 毫秒后console.log(2)回调推入 Event Queue 中
  • new Promise ,同步任务,主线程直接执行
  • .then ,异步任务,放到 Event Table
  • console.log(3),同步任务,主线程执行

所以按照分析,它的结果应该是 1 => 'new Promise' => 3 => 2 => 'then'

但是实际结果是:1=>'new Promise'=> 3 => 'then' => 2

出现分歧的原因在于异步任务执行顺序,事件队列其实是一个“先进先出”的数据结构,排在前面的事件会优先被主线程读取

例子中 setTimeout回调事件是先进入队列中的,按理说应该先于 .then 中的执行,但是结果却偏偏相反

原因在于异步任务还可以细分为微任务与宏任务

微任务

一个需要异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前

常见的微任务有:

  • Promise.then

  • MutaionObserver

  • Object.observe(已废弃;Proxy 对象替代)

  • process.nextTick(Node.js)

宏任务

宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合

常见的宏任务有:

  • script (可以理解为外层同步代码)
  • setTimeout/setInterval
  • UI rendering/UI事件
  • postMessage、MessageChannel
  • setImmediate、I/O(Node.js)

这时候,事件循环,宏任务,微任务的关系如图所示

按照这个流程,它的执行机制是:

  • 执行一个宏任务,如果遇到微任务就将它放到微任务的事件队列中
  • 当前宏任务执行完成后,会查看微任务的事件队列,然后将里面的所有微任务依次执行完

标签:异步,console,log,JavaScript,任务,循环,Promise,事件,执行
From: https://www.cnblogs.com/chccee/p/17060977.html

相关文章

  • javaScript数组的sort()方法
    javaScript数组的sort()方法:今天再学习javaScript的数组的Array.sort()方法时,遇到了一个很有意思的问题,这个方法,直接调用,其实并不会得到我们想要的排序,而是会以一种很机械......
  • JavaScript学习笔记—instanceof和hasOwn
    1.instanceof用来检查一个对象是否是一个类的实例检查的是对象的原型链上是否有该类实例(只要原型链上有该类实例,就会返回true)Object是所有对象的原型,所以任何对象和Ob......
  • JavaScript trim() 方法
    JavaScripttrim()方法JavaScriptString对象去除字符串的头尾空格:varstr="Runoob";alert(str.trim());输出结果:Runoob定义和用法:trim()方法用于删......
  • JavaScript学习笔记—原型对象
    1.访问一个对象的原型对象(1)对象.__proto__(2)Object.getPrototypeOf(对象)一般用第二种,第一种不安全2.原型对象中的数据(1)对象中的数据(属性、方法等)(2)constructor(对象......
  • JavaScript精简(基于node.js)
    目录1、基本语法2、变量3、数据类型3.1、数字型Number3.2、字符串类型String3.3、布尔型Boolean3.4、Undefined、Null3.5、获取变量的数据类型3.6、数据类型的转化4、运......
  • 「学习笔记」循环矩阵行列式
    无证明,小记。\[\det\begin{bmatrix}a_0&a_1&a_2&\cdots&a_{n-1}\\a_{n-1}&a_0&a_1&\cdots&a_{n-2}\\a_{n-2}&a_{n-1}&a_0&\cdots&a_{n-3}\\\vdots&\vdots&\vdots&\dd......
  • 用pageOffice控件实现 office 文档在线编辑Word 打开文档后在页面里触发事件
    OA办公中,业务需要编辑打开word文档后执行一些js操作怎么实现编辑打开word文档后执行一些js操作呢?2实现方法通过pageOffice实现简单的在线打开编辑word时,通过设置关......
  • while循环(先判断后循环)和do-while循环(先循环一遍再判断)
    while循环                                                  ......
  • py之循环,函数
    循环a=1whilea<10: print(a) a+=1 a=[123,1235,123124,1231]whilea: a1=a.pop() print(a1) fora1ina: print(a1) foriinrange(4): print(a[i]) ......
  • p21_事件传参与数据同步
    事件绑定在事件处理函数中为data中的数据赋值通过调用this.setData(dataObject)方法,可以给页面data中的数据重新赋值,示例如下:事件传参小程序中的事件传参......