第一步先搞清楚兩件事:
Node.js 是 單執行緒(single-threaded) 的,但它能同時處理很多事情,靠的就是 Event Loop。
可以想像 Node.js 的工作流程:
今天我用 setTimeout
、setImmediate
、process.nextTick
來感受一下 Event Loop 的順序。
console.log("開始");
setTimeout(() => {
console.log("setTimeout");
}, 0);
setImmediate(() => {
console.log("setImmediate");
});
process.nextTick(() => {
console.log("process.nextTick");
});
console.log("結束");
執行結果通常會是:
開始
結束
process.nextTick
setTimeout
setImmediate
解釋:
process.nextTick
:會在目前這個階段結束後「馬上」執行(比 setTimeout 還快)setTimeout(fn, 0)
:丟到 Event Loop 的 timer 階段,等到主程式跑完才執行setImmediate
:等到 check 階段 才跑,通常比 setTimeout 晚這個順序一開始很難記,但實際跑過一次就會有感覺。
寫 Node.js 不可能把所有程式都塞在同一支檔案,所以必須要學會「模組化」。
utils.js
function add(a, b) {
return a + b;
}
module.exports = { add };
index.js
const { add } = require("./utils");
console.log(add(2, 3)); // 5
utils.js
export function add(a, b) {
return a + b;
}
index.js
import { add } from "./utils.js";
console.log(add(2, 3)); // 5
注意:ESM 在 Node.js 要記得設定 "type": "module"
(放在 package.json 裡)。
今天的實作我分成兩部分:
跑一遍 setTimeout
、setImmediate
、process.nextTick
,感受它們執行順序的差別。
math.js
:裡面 export 一個 add
函式app.js
:import 這個函式,拿來做簡單運算這樣就能清楚體會模組拆分的好處:檔案更乾淨、功能更獨立。
今天最有感的有兩點:
process.nextTick
比 setTimeout
還要快。require
和 import
都能拆檔案,但新的專案還是建議用 ESM(import/export),語法比較直覺。整體來說,今天算是 Node.js 的暖身。