惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
量子位
The Cloudflare Blog
美团技术团队
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 三生石上(FineUI控件)
T
Tor Project blog
博客园 - 司徒正美
宝玉的分享
宝玉的分享
T
Threatpost
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Secure Thoughts
T
Threat Research - Cisco Blogs
Hacker News: Ask HN
Hacker News: Ask HN
Jina AI
Jina AI
博客园 - 聂微东
A
Arctic Wolf
I
Intezer
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
小众软件
小众软件
T
Tailwind CSS Blog
The Hacker News
The Hacker News
L
LINUX DO - 最新话题
Hacker News - Newest:
Hacker News - Newest: "LLM"
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
TaoSecurity Blog
TaoSecurity Blog
Project Zero
Project Zero
博客园 - 叶小钗
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Cloudbric
Cloudbric
雷峰网
雷峰网
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
大猫的无限游戏
大猫的无限游戏
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Troy Hunt's Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
V2EX - 技术
V2EX - 技术
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog

Sanonz

使用 Invox Setup 实现 Electron 安装包界面美化 用 VS Code 编辑器开发 STM32 嵌入式 使用 FontCreator 编辑字体库 | Sanonz 使用 React Context API 和 Hooks 实现全局状态管理和性能优化 使用 Phonegap + Cordova 搭建混合开发平台 利用 Github Actions 自动部署 Hexo 博客 在 WEB 端实现亮/暗主题跟随系统功能 | Sanonz Metalness vs Specular Workflows for PBR Shading 以太坊概念与使用 wep3/infura 实现以太币及合约币交易流程 | Sanonz 实现树莓派(Raspberry Pi)联网发送本机IP到绑定的微信 | Sanonz 使用 Three.js 的 RenderTarget 实现离屏渲染 使用 redux-store-provider 简化 react 开发流程 浏览器 HTTP 并发请求规则探讨 | Sanonz WebAssembly 从入门到吃鸡 | Sanonz Let's Encrypt 使用教程,免费的 SSL 证书,让你的网站拥抱 HTTPS Let's Encrypt 使用教程,免费的 SSL 证书,让你的网站拥抱 HTTPS Ubuntu 搭建 php、mysql、nginx 开发环境 | Sanonz WebGL 三维教程 - 绘制矩形和点(二) | Sanonz WebGL 三维教程 - WebGL 介绍(一) Hexo 搭建静态博客与 hexo-theme-concise 主题使用教程 | Sanonz
JavaScript Event Loop、Micro Task、Macro Task
Sanonz · 2018-02-24 · via Sanonz

Event Loop

Event Loop:事件循环、Micro Task:微任务、Macro Task:宏任务

我们知道 JavaScript 是单线程语言,一心不能二用,也就是说它只能把一件事干完才能去干另一件事,但前端的一些任务是非常耗时的,比如网络请求,定时器和事件监听,如果让它们和别的任务一样,都老老实实的排队等待执行的话,执行效率会非常的低,甚至导致页面的假死。所以为了保证使用流畅,浏览器采用了 Event Loop 事件循环系统来管理,把那些耗时的任务放入 task queues 栈中,等主程序执行完再执行 task queues 中的任务,通常使用回调函数监听 task queues 中的任务状态。

在其它语言中可以迟延执行,比如 C 语言的 sleep(3) 可以迟延 3 秒执行后边的逻辑,但是在 JavaScript 中是没有这样的操作(除了 alertconfrimprompt 和异步 xhr,官方说这些是历史遗留的错误设计😂),只能使用异步方式去模拟,模拟的实际也不是真正意义上的 sleep 效果。

示例代码

在讨论 Micro Task、Macro Task 之前我们先来看一个例子,分析以下代码并思考 log 打的印顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
console.log('script start');

setTimeout(() => {
console.log('setTimeout 1');
});

Promise.resolve()
.then(() => {
console.log('promise 1');
})
.then(() => {
console.log('promise 2');
});

console.log('script end');

运行结果为

1
2
3
4
5
script start
script end
promise 1
promise 2
setTimeout 1

有人可能会有疑问,为什么不是按顺序输出?又或者是这样

1
2
3
4
5
script start
script end
setTimeout 1
promise 1
promise 2

Micro Task、Macro Task

想要搞明白这个问题,首先要了解 Event Loop 下的 Micro TaskMacro Task,在运行主程序时会把异步逻辑根据情况推到 Micro Task 或者 Macro Task 栈中,具体规则如下

以下情况会推到 Micro Task 栈中

  • process.nextTick
  • Promise
  • Object.observe
  • MutationObserver

以下情况会推到 Macro Task 栈中

  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI render

然后再来看实例代码的实际执行逻辑

  1. 执行 console.log('script start') 直接输出
  2. 执行 setTimeout 把回调函数放入 Macro Task 栈中
  3. 执行 Promise 把两个 then 的回调函数放入 Micro Task 栈中
  4. 执行 console.log('script end') 直接输出
  5. 执行 Micro Task 中所有任务
    1. 执行 console.log('promise 1') 直接输出
    2. 执行 console.log('promise 2') 直接输出
  6. 执行 Macro Task 中所有任务
    1. 执行 console.log('setTimeout 1') 直接输出

结束语

事件循环的顺序,决定了 JavaScript 代码的执行顺序。它从 script (整体代码) 开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的 Micro Task。当所有可执行的 Micro Task 执行完毕之后。循环再次从 Macro Task 开始,找到其中一个任务队列执行完毕,然后再执行所有的 Micro Task,在执行 Micro Task、Macro Task 的时候同样遵循 Event Loop 原则,就这样一直循环下去。

参考站点