react navite浏览器 Event Loop 和 Node Event Loop 的区别
如果你说的是 React Native 中的 JS Event Loop 和 Node.js Event Loop,核心区别可以先记成一句话:
React Native:JS Event Loop 主要由 RN 的 JavaScript Runtime + 原生平台调度机制驱动。
Node.js:JS Event Loop 由 Node.js + libuv 驱动,并且有非常明确的多个 Event Loop Phase。
1. 先看整体架构
React Native
┌──────────────────────────────┐
│ React Native App │
│ │
│ ┌────────────────────────┐ │
│ │ JavaScript Runtime │ │
│ │ Hermes / JSC │ │
│ │ │ │
│ │ JS Call Stack │ │
│ │ Microtask Queue │ │
│ │ Timer / Promise ... │ │
│ └───────────┬────────────┘ │
│ │ │
│ RN JS Event Loop │
│ │ │
│ ┌───────────▼────────────┐ │
│ │ Native iOS / Android │ │
│ │ │ │
│ │ Main/UI Thread │ │
│ │ Native Modules │ │
│ │ Network / Timer / etc. │ │
│ └─────────────────────────┘ │
└──────────────────────────────┘
React Native 的 JS 线程本质上运行的是:
JavaScript
↓
Hermes / JSC
↓
JS Event Loop
但是它不是浏览器 Event Loop 的完整复制品,也不是 Node.js 的 libuv Event Loop。
2. Node.js Event Loop
Node.js 的 Event Loop 可以认为是:
┌───────────────┐
│ timers │
└───────┬───────┘
↓
┌───────────────┐
│ pending │
│ callbacks │
└───────┬───────┘
↓
┌───────────────┐
│ idle / prepare│
└───────┬───────┘
↓
┌───────────────┐
│ poll │
│ I/O callbacks │
└───────┬───────┘
↓
┌───────────────┐
│ check │
│ setImmediate │
└───────┬───────┘
↓
┌───────────────┐
│ close │
│ callbacks │
└───────────────┘
│
└──────→ 下一轮
这是 Node 最大的特点。
例如:
setTimeout(() => {
console.log('timeout');
}, 0);
setImmediate(() => {
console.log('immediate');
});
Node 中两者的执行顺序和当前代码所处的上下文有关。
尤其:
fs.readFile('test.txt', () => {
setTimeout(() => {
console.log('timeout');
}, 0);
setImmediate(() => {
console.log('immediate');
});
});
这里通常:
immediate
timeout
因为 fs callback 在 poll phase 中执行,而 setImmediate 属于 check phase。
3. React Native 没有 Node 那套 Phase
这是非常重要的区别。
你不能把 RN 理解成:
timers
↓
poll
↓
check
↓
close
RN 没有 Node.js 的:
setImmediate()
process.nextTick()
这种 Node 专属机制。
React Native 的 JS 环境更接近:
JS Call Stack
↓
执行同步代码
↓
Microtask Queue
↓
Timers / RN 调度
↓
下一次 JS Event Loop
例如:
console.log('A');
setTimeout(() => {
console.log('B');
}, 0);
Promise.resolve().then(() => {
console.log('C');
});
console.log('D');
基本可以理解成:
A
D
C
B
也就是:
同步任务
↓
Promise Microtask
↓
Timer
这点和浏览器非常接近。
4. RN vs 浏览器 vs Node
可以这样记:
| Browser | React Native | Node.js | |
|---|---|---|---|
| JS Runtime | V8 / SpiderMonkey 等 | Hermes / JSC | V8 |
| Event Loop | 浏览器实现 | RN + Runtime | Node + libuv |
| Microtask | ✅ | ✅ | ✅ |
| Promise | ✅ | ✅ | ✅ |
| setTimeout | ✅ | ✅ | ✅ |
| setInterval | ✅ | ✅ | ✅ |
| requestAnimationFrame | ✅ | ✅ | ❌ |
| DOM | ✅ | ❌ | ❌ |
process.nextTick | ❌ | ❌ | ✅ |
setImmediate | ❌ | ❌/不应依赖 | ✅ |
| libuv | ❌ | ❌ | ✅ |
| I/O Poll Phase | 浏览器内部实现 | Native 平台机制 | ✅ 明确存在 |
| UI Rendering | 浏览器控制 | Native UI | ❌ |
所以:
React Native 更接近 Browser Event Loop,而不是 Node Event Loop。
但 RN 又不能简单等同于浏览器,因为 RN 没有 DOM、Rendering Pipeline 也完全不同。
5. React Native 最大的特殊点:JS Thread
RN 开发中 Event Loop 最容易和 JS Thread 搞混。
比如:
function heavyTask() {
for (let i = 0; i < 10000000000; i++) {}
}
heavyTask();
这不是说:
Event Loop 坏了。
而是:
JS Thread
┌─────────────────────────────┐
│ heavyTask() │
│ ██████████████████████████ │
│ │
│ Promise callback │ ← 等待
│ setTimeout callback │ ← 等待
│ React update │ ← 等待
└─────────────────────────────┘
JS Call Stack 被长任务占住了。
所以:
setTimeout(fn, 0);
并不是:
0ms 后马上执行
而是:
至少等到 timer 到期,并且 JS Thread 有机会执行它。
6. RN 为什么会出现「卡 UI」
这是 RN 和 Node 非常重要的区别。
假设:
for (let i = 0; i < 1e10; i++) {}
RN:
JS Thread
│
│ 💥 被占满
↓
Event Loop 无法继续
↓
JS callbacks 无法执行
↓
JS 驱动的 UI 更新无法及时处理
↓
用户感觉卡顿
Node:
Node JS Thread
│
│ heavy computation
↓
Event Loop 被阻塞
↓
HTTP callbacks
Timer callbacks
I/O callbacks
全部延迟
所以两者有一个共同原则:
JavaScript 是单线程执行的,长时间同步任务都会阻塞 Event Loop。
只是 RN 最终体现为界面交互/动画卡顿,Node 更多体现为请求、I/O、Timer 响应变慢。
7. Microtask 是两者都非常重要的东西
例如:
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
});
console.log('4');
RN / Browser 可以理解成:
Call Stack
1
4
↓
Microtask Queue
3
↓
Task / Timer
2
结果:
1
4
3
2
Node 也是:
1
4
3
2
但 Node 还有一个特殊机制:
process.nextTick()
例如:
console.log('1');
process.nextTick(() => {
console.log('2');
});
Promise.resolve().then(() => {
console.log('3');
});
console.log('4');
Node 中:
1
4
2
3
因为:
process.nextTick
↓
Promise Microtask
↓
Event Loop Phase
所以如果你在 RN 代码里看到:
process.nextTick(...)
要特别警惕:
这是 Node 思维,不应该把 Node 的 Event Loop 机制直接套到 RN。
8. RN 还有一个非常重要的东西:Frame
RN 做动画时,你经常会遇到:
requestAnimationFrame(() => {
...
});
它和:
setTimeout(fn, 0);
完全不是一回事。
可以粗略理解:
RN / Native UI
│
Frame / VSync
│
┌───────────┴───────────┐
↓ ↓
JS Thread UI Thread
│ │
JS animation Native rendering
例如:
function animate() {
requestAnimationFrame(() => {
updateAnimation();
animate();
});
}
它的目标是跟随屏幕刷新节奏。
而:
setTimeout(updateAnimation, 16);
只是一个 Timer。
因此在 RN 中:
Timer ≠ Frame。
这也是为什么 React Native 动画性能问题不能只用「Event Loop」解释。
9. 新架构下还要考虑 JSI / UI Thread
如果你研究的是现代 React Native(Fabric + TurboModules + JSI),Event Loop 的问题会更加有意思。
传统模型可以简单理解:
JS Thread
│
│ Bridge
↓
Native Thread
而新架构更多是:
JS Runtime
│
│ JSI
↓
C++ / Native
│
├── Fabric
├── TurboModules
└── Native
因此不能再简单理解成:
JS Event Loop
↓
Bridge Queue
↓
Native Event Loop
尤其是 JSI 是同步调用能力,这和传统 Bridge 的异步消息模型区别很大。
10. 最后给你一个最好记的模型
如果你是做 React Native 前端开发,建议脑子里这样记:
Browser
JS
│
├── Call Stack
│
├── Microtask Queue
│
├── Task Queue
│
└── Rendering
React Native
JS Runtime
│
├── Call Stack
│
├── Microtask Queue
│
├── Timer / RN callbacks
│
└── Native / UI / Frame
Node.js
Node
│
├── Call Stack
│
├── nextTick Queue
│
├── Microtask Queue
│
└── libuv Event Loop
│
├── timers
├── pending callbacks
├── poll
├── check
└── close
一句话总结:
RN 的 Event Loop 重点是「JS Thread + Microtask + Timer + Frame/UI 调度」;Node 的 Event Loop 重点是「V8 + libuv + 多 Phase + I/O」。
如果你正在准备 RN 面试,最值得继续搞懂的是 「Promise → setTimeout → requestAnimationFrame → React setState 在 RN 中到底谁先执行」,这个比单纯背 Event Loop Phase 更实用。
更多推荐



所有评论(0)