Scheduler: postTask() 方法
postTask()
是 Scheduler
接口的方法,用于根据 调度 任务的 优先级 添加任务。
此方法允许用户可选地指定任务运行前的最短延迟时间、任务的优先级以及可用于修改任务优先级和/或中止任务的信号。它返回一个 Promise,该 Promise 通过任务回调函数的结果解析,或者通过中止原因或任务中抛出的错误拒绝。
任务优先级可以是 可变或不可变 的。如果任务优先级永远不需要更改,则应使用 options.priority
参数设置(然后将忽略通过信号设置的任何优先级)。您仍然可以将 AbortSignal
(没有优先级)或 TaskSignal
传递给 options.signal
参数以中止任务。
如果需要更改任务优先级,则必须不设置 options.priority
参数。相反,应该创建一个 TaskController
,并将它的 TaskSignal
传递给 options.signal
。任务优先级将从信号优先级初始化,并且稍后可以使用信号关联的 TaskController
修改它。
如果未设置优先级,则任务优先级默认为 "user-visible"
。
如果指定了延迟且大于 0,则任务的执行将至少延迟这么多毫秒。否则,任务将立即安排进行优先级排序。
语法
postTask(callback)
postTask(callback, options)
参数
callback
-
实现任务的回调函数。回调的返回值用于解析此函数返回的 Promise。
options
可选-
任务选项,包括
priority
可选-
任务的不可变 优先级。以下之一:
"user-blocking"
、"user-visible"
、"background"
。如果设置,则此优先级将用于任务的整个生命周期,并且将忽略signal
上设置的优先级。 signal
可选-
一个
TaskSignal
或AbortSignal
,可用于中止任务(来自其关联的控制器)。如果设置了
options.priority
参数,则无法更改任务优先级,并且将忽略信号上的任何优先级。否则,如果信号是TaskSignal
,则其优先级用于设置初始任务优先级,并且信号的控制器以后可以使用它来更改任务优先级。 delay
可选-
将任务添加到调度程序队列后的最短时间(以毫秒为单位)。实际延迟可能高于指定延迟,但不会低于指定延迟。默认延迟为 0。
返回值
返回一个 Promise
,该 Promise 通过 callback
函数的返回值解析,或者可能通过 signal
的中止原因(AbortSignal.reason
)拒绝。Promise 也可能因回调在执行期间抛出的错误而被拒绝。
示例
以下示例是 优先级任务调度 API > 示例 中提供的实时示例的略微简化版本。
功能检查
通过测试全局“this
”中的 scheduler
属性(例如,窗口范围内的 Window.scheduler
或工作线程范围内的 WorkerGlobalScope.scheduler
)来检查是否支持优先级任务调度。
例如,如果此浏览器支持该 API,则以下代码将记录“功能:受支持”。
// Check that feature is supported
if ("scheduler" in this) {
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
此方法也可以与 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
参数设置 任务优先级。以这种方式设置的优先级无法更改(是 [不可变的]/en-US/docs/Web/API/Prioritized_Task_Scheduling_API#mutable_and_immutable_task_priority))。
下面我们发布了两组三个任务,每组成员的优先级按相反顺序排列。最后一个任务具有默认优先级。运行时,每个任务都简单地记录其预期顺序(我们没有等待结果,因为我们不需要等待结果就可以显示执行顺序)。
// three tasks, in reverse order of priority
scheduler.postTask(() => console.log("bckg 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("bckg 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) bckg 1 bckg 2
更改任务优先级
任务优先级 也可以从传递给可选第二个参数中 postTask()
的 TaskSignal
获取其初始值。如果以这种方式设置,则可以使用与信号关联的控制器更改任务的优先级 [可以更改]/en-US/docs/Web/API/Prioritized_Task_Scheduling_API#mutable_and_immutable_task_priority)。
注意:仅当 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 |
浏览器兼容性
BCD 表格仅在启用了 JavaScript 的浏览器中加载。