notes
  • Introduction
  • 语言
    • JS
      • JS原型到原型链
      • JS继承的实现
      • this对象
      • Promise基本概念
      • Promise实现
      • Promise实战
      • JS的EventLoop
      • JS容易出现误区的运算符
      • JS容易出现误区的操作符
      • JS深拷贝
      • JS节流与防抖
      • ES5实现原生/ES6方法
    • TS
      • 声明文件
      • 项目配置
    • CSS
      • CSS引入方式以及优先级计算
      • BFC神奇背后的原理-文摘
      • 回流reflow与重绘repaint
      • 三栏式布局
      • 垂直居中
      • 清除浮动的方法
      • 移动端适配方案
      • 纯CSS斜切角实现
      • CSS揭秘
      • 背景图片轮播
      • CSS绘制序列帧动画
      • transform实现一个多面体
    • HTML
  • ES6
  • Node.js
    • xxx
  • 前端框架
    • Vue.js
      • Vue双向数据绑定原理
      • Vue-Router原理及实现
    • React
    • AngularJS
  • 工程构建
    • Webpack
      • 01-webpack概述及背景
      • 03-webpack热更新原理
      • 04-splitChunks原理分析
      • 05-webpack工作流程
      • 07-webpack构建流程
      • 07-webpack构建流程
      • 10-webpack 如何进行性能分析
    • Gulp
    • Lint
      • ESLint
      • TSLint
    • Bable
  • 工程化
    • 模块化
    • 组件化
    • 规范化
      • 编码规范
    • 自动化
  • 运维
    • Nginx
    • GIT
    • CDN
    • VPS
    • DBA
  • 小程序
  • 跨端
  • 测试
  • 计算机技术
    • 计算机网络
      • 同源策略到前端跨域解决方案
      • TCP数据传输
      • TCP和UDP的区别
      • HTTP协议概述
      • HTTP缓存详解
      • HTTPS以及SSL建立过程
      • HTTPS的七个误解(译文)
      • cookie与Session机制区别以及Cookie SessionStorage LocalStorage异同
      • HTTP状态码Status
      • DNS原理入门
      • 网络攻击与防御
      • HTTP转发与重定向
      • 登录认证设计
    • 操作系统
      • shell脚本命令
    • Linux
      • Linux命令大全
      • vim命令
    • 浏览器
      • 浏览器内核、JS 引擎、页面呈现原理及其优化
      • 九种浏览器端缓存机制概览
      • 性能优化-网络请求方面
      • webkit解析CSS过程详解
  • 前端面试
    • 算法
Powered by GitBook
On this page
  • 宏任务和微任务
  • 宏任务
  • 微任务
  • 浏览器的EventLoop
  • Node的EventLoop
  • 不同点
  • EventLoop
  • 参考
  1. 语言
  2. JS

JS的EventLoop

JavaScript是单线程,非阻塞的。

代码执行过程中,同步代码按顺序直接入栈,异步代码(宏任务、微任务)进队列,等待入栈执行。

宏任务和微任务

宏任务和微任务的区别请上网学习

宏任务

任务
浏览器
Node

setTimeout()

✅

✅

setInterval()

✅

✅

IO

✅

✅

requestAnimationFrame

✅

❌

postMessage

✅

❌

setImmediate()

❌

✅

微任务

任务
浏览器
Node

Promise

✅

✅

process.nextTick

❌

✅

MutationObserverH5新增

✅

❌

浏览器的EventLoop

在当前执行栈为空时,主线程会查看微任务队列是否有事件存在

  • 存在,依次执行队列中的事件对应的回调,直到微任务队列为空,然后去宏任务队列中取出最前面的事件,把当前的回调加到当前指向栈。

  • 如果不存在,那么再去宏任务队列中取出一个事件并把对应的回到加入当前执行栈;

当前执行栈执行完毕后时会立刻处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

在事件循环中,每进行一次循环操作称为tick,每一次tick的任务处理模型是比较复杂的,但关键步骤如下:

  1. 执行一个宏任务(栈中没有就从事件队列中获取)

  2. 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中

  3. 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)

  4. 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染

  5. 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

Node的EventLoop

不同点

  • Node 中事件循环的实现依赖libuv引擎。

  • Node10以前,microTask 在事件循环的的各个阶段执行

  • Node10以后,变得和浏览器一致,一旦一个阶段里的宏任务,就立刻执行所有的microTask

EventLoop

node官网对于事件循环操作顺序的图解

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

阶段描述:

  • 定时器:本阶段执行已经被setTimeout()和setInterval()的调度回调函数。

  • 待定回调:执行延迟到下一个循环迭代的I/O回调。

  • idle, prepare:仅系统内部使用。

  • 轮询:检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和setImmediate()调度的之外),其余情况node将在适当的时候在此阻塞。

  • 检测:setImmediate()回调函数在这里执行。

  • 关闭的回调函数:一些关闭的回调函数,如:socket.on('close', ...)。

对于各个阶段的具体解释和案例,参考官网。

参考

PreviousPromise实战NextJS容易出现误区的运算符

Last updated 3 years ago

Node.js 事件循环,定时器和 process.nextTick()
JavaScript 运行机制详解:再谈Event Loop
浏览器与Node的事件循环(Event Loop)有何区别?