XingYun blog
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具

XingYun

冲!
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具
  • leaflet改变坐标原点
  • 补间动画gsap与tween
  • 文字转语音mp3文件
  • JavaScript引入
  • JavaScript高级程序设计阅读笔记
  • Javascript函数参数按值传递传递
  • JS防抖和节流
  • 手写JS常用方法
  • 手写Promise
  • JS Event Loop
    • 重排和重绘
    • em、px、rem、vh、vw 区别
    • css也需要性能优化
    • 图解 js 原型链
    • js函数参数按值传递
    • BOM浏览器对象模型
    • DOM
    • 事件
    • js对象数组sort按需排序
    • 文件上传功能技术选型和前后端实现
    • 前端图片处理
    • 让你的JavaScript代码简单又高效
    • BEM:class命名规范
    • 前端规范-CSS属性那么多(杂),怎么排序
    • TypeScript Tips
    • jsx
    • canvas基础
    • 前端日志
    • 浏览器存储
    • CSS世界阅读笔记
    • CSS揭秘阅读笔记
    • js变量命名常用规范词
    • 你不知道的JavaScript阅读笔记
    • js对象的底层数据结构
    • js判断数据类型
    • JS浮点数精度问题和解决办法
    • js作用域
    • js堆栈溢出和内存泄漏
    • 浏览器是如何渲染页面的
    • 疑难杂症和踩坑问题合集
    • 免费在线API收集
    • 原生JS实现Ajax请求
    • cookie、session、localStorage、sessionStorage的区别
    • Sass与Less
    • arrayBuffer、blob、file对象
    • TypeScript基础
    • 前端
    XingYun
    2021-11-27
    目录

    JS Event Loop

    # 一.Javascript的执行机制

    JavaScript 是单线程。

    单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。

    如果前一个任务耗时很长,后一个任务就不得不一直等着。

    为了协调事件(event),用户交互(user interaction),脚本(script),渲染(rendering),网络(networking)等,用户代理(user agent)必须使用事件循环(event loops)。

    JS执行过程中,主线程从"任务队列"中读取执行事件,这个过程是循环不断的,这个机制被称为事件循环。

    Event Loop是javascript的执行机制

    # 二.宏任务微任务

    "任务队列"中的任务分为两种

    宏任务:正常的异步任务都是宏任务,最常见的就是定时器setInterval、setTimeout、IO任务

    微任务:微任务出现比较晚,process.nextTick(callback)、Promise和async属于微任务(当然,async就是promise)

    此机制具体如下:

    主线程会不断从任务队列中按顺序取任务执行,每执行完一个任务都会检查microtask队列是否为空(执行完一个任务的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask。然后再进入下一个循环去任务队列中取下一个任务执行。

    当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件**,** 然后再去宏任务队列中取出一个事件。

    同一次事件循环中微任务永远在宏任务之前执行

    所以其实微任务就是得到优先执行的异步任务

    按照官方的设想,任务之间是不平等的,有些任务对用户体验影响大,就应该优先执行,而有些任务属于背景任务(比如定时器),晚点执行没有什么问题,所以设计了这种优先级队列的方式

    # 三、nodejs的Event-loop

    #

    node 和 浏览器 eventLoop的最主要的区别在于浏览器中的微任务是在每个相应的宏任务中执行的,而nodejs中的微任务是在不同阶段之间执行的。

    # 4.代码

    了解原理后看例子:

    setTimeout(()=>{
      console.log('setTimeout1')
    },0)
    let p = new Promise((resolve,reject)=>{
      console.log('Promise1')
      resolve()
    })
    p.then(()=>{
      console.log('Promise2')    
    })
    复制代码
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    容易得出输出结果是Promise1,Promise2,setTimeout1

    # 四、JS为什么要区分微任务和宏任务?

    个人认为,是为了给任务分级, 分级的目的是为了对不同级别的任务区分对待。

    代码都是对现实世界的抽象,机场也有vip通道,任务分优先级是很正常的,要不然紧急任务怎么插队。

    一个Event Loop,Microtask 是在 Macrotask 之后调用,Microtask 会在下一个Event Loop 之前执行调用完,并且其中会将 Microtask 执行当中新注册的 Microtask 一并调用执行完,然后才开始下一次 Event loop,所以如果有新的 Macrotask 就需要一直等待,等到上一个 Event loop 当中 Microtask 被清空为止。

    由此可见, 我们可以在下一次 Event loop 之前进行插队。如果不区分 Microtask 和 Macrotask,那就无法在下一次 Event loop 之前进行插队,其中新注册的任务得等到下一个 Macrotask 完成之后才能进行,这中间可能你需要的状态就无法在下一个 Macrotask 中得到同步。状态的同步对于视图来说至关重要,这也就牵扯到了为什么 javascript 是单线程的原因所在。

    #JavaScript
    上次更新: 2023/04/05, 09:41:10
    手写Promise
    重排和重绘

    ← 手写Promise 重排和重绘→

    最近更新
    01
    JavaScript-test
    07-20
    02
    二维码的原理
    07-20
    03
    利用ChatGPT优化代码
    07-20
    更多文章>
    Theme by Vdoing | Copyright © 2021-2023 XingYun | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式