在前一篇,我們探討了 Scheduler 與圖 (Graph) 的關係,並處理了記憶體與依賴管理的挑戰。
但在真實應用中,任務並不都是「同等級」的:
這時就需要 優先級 (Priority) 與 分層 Scheduler 的設計。
想像這個場景,使用者正在輸入文字 (input.onChange
),同時後台有一個大型計算任務(例如 chart re-render)。
如果兩者都放進同一個 queue,且無優先級控制,使用者輸入就可能被「卡住」,造成體驗不佳。
解法:讓 高優先級任務(輸入事件) 先處理,低優先級任務延後執行。
在現代前端框架中,通常會有類似以下的分級:
這樣可以確保:體驗最關鍵的互動永遠先執行。
除了優先級,另一個重要概念是「分層」。
我們可以將任務劃分成不同 層級 (layers),讓每個層都有獨立的 queue
,並用 Scheduler 來協調:
這種劃分方式有點像作業系統的 CPU Scheduler:不同類型的任務分開管理,避免互相干擾。
以下是一個簡化版的「分層 + 優先級」 Scheduler:
type Priority = "immediate" | "high" | "normal" | "low";
interface Job {
run(): void;
priority: Priority;
layer: "compute" | "ui" | "io" | "idle";
}
const queues: Record<Priority, Job[]> = {
immediate: [],
high: [],
normal: [],
low: [],
};
export function scheduleJob(job: Job) {
queues[job.priority].push(job);
requestFlush();
}
function requestFlush() {
queueMicrotask(flushJobs);
}
function flushJobs() {
// 按優先級執行
runQueue(queues.immediate);
runQueue(queues.high);
runQueue(queues.normal);
runQueue(queues.low);
}
function runQueue(queue: Job[]) {
while (queue.length > 0) {
const job = queue.shift()!;
job.run();
}
}
這是一個「單層優先級」範例,若要進一步分層,可以在
Job.layer
上再細分不同的 queue。
從單一 queue 到「優先級 + 分層」的 Scheduler,最大的目標就是:
在確保互動即時性的同時,最大化效能利用率。
這也是為什麼 React 引入 Concurrent Features、Vue 使用 job queue,而 Signal-based 系統也開始設計更細緻的 Scheduler。
下一篇,我們會更深入探討「Time-Slicing 與協作式排程 (Cooperative Scheduling)」,讓 scheduler 能在繁重任務中保持流暢的互動體驗。