Scheduler: postTask() 方法
注意:此功能在 Web Workers 中可用。
Scheduler 介面的 postTask() 方法用於根據 優先順序 來 排程 任務。
該方法允許使用者選擇性地指定任務的最小延遲執行時間、任務優先順序以及可用於修改任務優先順序和/或中止任務的訊號。它返回一個 Promise,該 Promise 會在任務回撥函式執行完畢後解析(返回其結果),或在任務被中止或丟擲錯誤時被拒絕。
任務優先順序可以是 可變的或不可變的。如果任務優先順序永遠不需要更改,則應使用 options.priority 引數進行設定(此時透過訊號設定的任何優先順序都將被忽略)。您仍然可以將 AbortSignal(無優先順序)或 TaskSignal 傳遞給 options.signal 引數來中止任務。
如果任務優先順序可能需要更改,則不得設定 options.priority 引數。相反,應該建立一個 TaskController,並將其 TaskSignal 傳遞給 options.signal。任務優先順序將從訊號優先順序初始化,之後可以使用訊號關聯的 TaskController 進行修改。
如果未設定優先順序,則任務優先順序預設為 "user-visible"。
如果指定了延遲並且大於 0,則任務的執行將被延遲至少這麼多毫秒。否則,任務將被立即排程進行優先順序排序。
語法
postTask(callback)
postTask(callback, options)
引數
回撥-
一個實現任務的回撥函式。回撥函式的返回值用於解析此函式返回的 Promise。
options可選-
任務選項,包括:
priority可選-
任務的不可變 優先順序。可能的值為:
"user-blocking"、"user-visible"、"background"。如果設定了此引數,則在任務的整個生命週期內將使用此優先順序,並且signal上設定的優先順序將被忽略。 signal可選-
一個
TaskSignal或AbortSignal,可用於中止任務(透過其關聯的控制器)。如果設定了
options.priority引數,則任務優先順序無法更改,並且將忽略訊號上的任何優先順序。否則,如果訊號是TaskSignal,則其優先順序用於設定初始任務優先順序,並且訊號的控制器之後可以使用它來更改任務優先順序。 delay可選-
任務將被新增到排程器佇列的最小時間(以整數毫秒為單位)。實際延遲可能高於指定值,但不會低於。預設延遲為 0。
返回值
返回一個 Promise,該 Promise 會使用 callback 函式的返回值進行解析,或者可能使用 signal 的中止原因(AbortSignal.reason)進行拒絕。在回撥執行期間丟擲的錯誤也可能導致 Promise 被拒絕。
示例
以下示例是 Prioritized Task Scheduling API > 示例 中提供的即時示例的簡化版本。
功能檢測
透過在全域性作用域(例如,視窗作用域中的 Window.scheduler 或工作執行緒作用域中的 WorkerGlobalScope.scheduler)中測試 scheduler 屬性,來檢查是否支援優先順序任務排程。
例如,下面的程式碼如果在瀏覽器中支援該 API,則會輸出 "Feature: Supported"。
// Check that feature is supported
if ("scheduler" in globalThis) {
console.log("Feature: Supported");
} else {
console.error("Feature: NOT Supported");
}
基本用法
任務被髮布,在第一個引數中指定回撥函式(任務),在可選的第二個引數中指定任務優先順序、訊號和/或延遲。該方法返回一個 Promise,該 Promise 在回撥函式執行完畢後解析,或因中止錯誤或函式中丟擲的錯誤而被拒絕。
由於它返回一個 Promise,因此 postTask() 可以 與鏈式 Promise 一起使用。下面我們展示如何使用 then 等待 Promise 解析,或使用 catch 等待 Promise 被拒絕。未指定優先順序,因此將使用預設優先順序 user-visible。
// A function that defines a task
function myTask() {
return "Task 1: user-visible";
}
// Post task with default priority: 'user-visible' (no other options)
// When the task resolves, Promise.then() logs the result.
scheduler
.postTask(myTask, { signal: abortTaskController.signal })
.then((taskResult) => console.log(`${taskResult}`)) // Log resolved value
.catch((error) => console.error("Error:", error)); // Log error or abort
該方法也可以在 async function 中與 await 一起使用。下面的程式碼顯示瞭如何使用此方法等待一個 user-blocking 任務。
function myTask2() {
return "Task 2: user-blocking";
}
async function runTask2() {
const result = await scheduler.postTask(myTask2, {
priority: "user-blocking",
});
console.log(result); // 'Task 2: user-blocking'.
}
runTask2();
永久優先順序
可以透過可選的第二個引數中的 priority 引數設定 任務優先順序。以這種方式設定的優先順序無法更改(是 不可變的)。
下面我們釋出兩組共三項任務,每組任務按優先順序倒序排列。最後一項任務具有預設優先順序。執行時,每項任務都會簡單地記錄其預期順序(我們不需要等待結果,因為要顯示執行順序,無需等待)。
// three tasks, in reverse order of priority
scheduler.postTask(() => console.log("bkg 1"), { priority: "background" });
scheduler.postTask(() => console.log("usr-vis 1"), {
priority: "user-visible",
});
scheduler.postTask(() => console.log("usr-blk 1"), {
priority: "user-blocking",
});
// three more tasks, in reverse order of priority
scheduler.postTask(() => console.log("bkg 2"), { priority: "background" });
scheduler.postTask(() => console.log("usr-vis 2"), {
priority: "user-visible",
});
scheduler.postTask(() => console.log("usr-blk 2"), {
priority: "user-blocking",
});
// Task with default priority: user-visible
scheduler.postTask(() => {
console.log("usr-vis 3 (default)");
});
預期輸出如下所示:任務按優先順序順序執行,然後按宣告順序執行。
usr-blk 1 usr-blk 2 usr-vis 1 usr-vis 2 usr-vis 3 (default) bkg 1 bkg 2
更改任務優先順序
任務優先順序 也可以透過傳遞給 postTask() 的可選第二個引數中的 TaskSignal 來獲取初始值。如果以此方式設定,則可以使用與訊號關聯的控制器 隨後更改 任務優先順序。
注意: 僅當 postTask() 的 options.priority 引數未設定,並且 options.signal 是 TaskSignal(而不是 AbortSignal)時,使用訊號設定和更改任務優先順序才有效。
下面的程式碼首先展示瞭如何建立 TaskController,並在其 TaskController() 建構函式 中將其訊號的初始優先順序設定為 user-blocking。
然後,我們使用 addEventListener() 為控制器的訊號新增事件監聽器(我們也可以使用 TaskSignal.onprioritychange 屬性來新增事件處理程式)。事件處理程式使用事件上的 previousPriority 來獲取原始優先順序,並使用事件目標上的 TaskSignal.priority 來獲取新/當前優先順序。
// Create a TaskController, setting its signal priority to 'user-blocking'
const controller = new TaskController({ priority: "user-blocking" });
// Listen for 'prioritychange' events on the controller's signal.
controller.signal.addEventListener("prioritychange", (event) => {
const previousPriority = event.previousPriority;
const newPriority = event.target.priority;
console.log(`Priority changed from ${previousPriority} to ${newPriority}.`);
});
最後,釋出任務,傳遞訊號,然後透過在控制器上呼叫 TaskController.setPriority() 將優先順序立即更改為 background。
// Post task using the controller's signal.
// The signal priority sets the initial priority of the task
scheduler.postTask(() => console.log("Task 1"), { signal: controller.signal });
// Change the priority to 'background' using the controller
controller.setPriority("background");
預期輸出如下所示。請注意,在這種情況下,優先順序在任務執行之前被更改,但它也可以在任務執行時被更改。
// Expected output
// Priority changed from user-blocking to background.
// Task 1
中止任務
可以使用 TaskController 和 AbortController 以完全相同的方式中止任務。唯一的區別是,如果您還想設定任務優先順序,則必須使用 TaskController。
下面的程式碼建立一個控制器,並將其訊號傳遞給任務。然後任務立即被中止。這會導致 Promise 被 AbortError 拒絕,該錯誤在 catch 塊中被捕獲並記錄。請注意,我們也可以偵聽 TaskSignal 或 AbortSignal 上觸發的 abort 事件,並在那裡記錄中止。
// Declare a TaskController with default priority
const abortTaskController = new TaskController();
// Post task passing the controller's signal
scheduler
.postTask(() => console.log("Task executing"), {
signal: abortTaskController.signal,
})
.then((taskResult) => console.log(`${taskResult}`)) // This won't run!
.catch((error) => console.error("Error:", error)); // Log the error
// Abort the task
abortTaskController.abort();
延遲任務
可以透過在 postTask() 的 options.delay 引數中指定一個整數毫秒數來延遲任務。這有效地將任務新增到優先順序佇列的超時中,就像使用 setTimeout() 建立的一樣。delay 是任務新增到排程器之前的最短時間;實際時間可能會更長。
下面的程式碼顯示了新增的兩個任務(作為箭頭函式),它們都帶有延遲。
// Post task as arrow function with delay of 2 seconds
scheduler
.postTask(() => "Task delayed by 2000ms", { delay: 2000 })
.then((taskResult) => console.log(`${taskResult}`));
scheduler
.postTask(() => "Next task should complete in about 2000ms", { delay: 1 })
.then((taskResult) => console.log(`${taskResult}`));
規範
| 規範 |
|---|
| 優先任務排程 # dom-scheduler-posttask |
瀏覽器相容性
載入中…