Prioritized Task Scheduling API

Prioritized Task Scheduling API

一种标准化的方法来优先处理属于应用程序的所有任务,无论它们是在网站开发人员的代码中定义的,还是在第三方库和框架中定义的
任务优先级是非常粗粒度的,并且基于任务是否阻止用户交互或以其他方式影响用户体验,或者可以在后台运行
基于 Promise 的,支持设置和更改任务优先级延迟添加到调度程序的任务中止任务以及监视优先级更改和中止事件的能力
windowworker 中都可用,使用全局对象上的 scheduler 属性

  • Scheduler.postTask: 接受一个回调函数(添加要调度的优先级任务)并返回一个 Promise

    • 默认优先级 user-visible 的任务,该任务具有固定的优先级且无法中止
    • 共有三种优先级(从最高到最低排序):user-blockinguser-visiblebackground
      • user-blocking: 阻止用户与页面交互的任务。 这包括将页面呈现到可以使用的位置,或者响应用户输入
      • user-visible: 对用户可见但不一定阻止用户操作的任务。 这可能包括呈现页面的非必要部分,例如非必要的图像或动画。
      • background: 不是时间紧迫的任务。 这可能包括日志处理或初始化渲染不需要的第三方库。
  • Scheduling.isInputPending: 检查事件队列中是否有挂起的输入事件, 表明用户正在尝试与页面交互

    避免在用户主动与页面交互时阻塞主线程,从而提供更流畅的用户体验。然而,通过只在必要时让步,我们可以在没有用户输入需要处理时继续运行当前任务。这也避免了任务被放置在队列的后面,排在其他非必要的浏览器启动的任务之后,这些任务被安排在当前任务之后。

    • navigator.scheguling.isInputPending()
      
  • 任务优先级也可以从可选的第二个参数中传递给 TaskSignalpostTask() 中获取其初始值。 如果以这种方式设置,则可以使用与信号相关联的控制器来改变任务的优先级。

    注意:使用信号设置和更改任务优先级仅在未设置 options.prioritypostTask() 参数,以及 options.signalTaskSignal(而不是 AbortSignal)时有效。

  • 可以使用 TaskControllerAbortController 以完全相同的方式中止任务。 唯一的区别是,如果您还想设置任务优先级,则必须使用 TaskController

  • 通过在 options.delaypostTask() 参数中指定整数毫秒数,可以延迟任务。 这有效地将任务添加到超时的优先级队列中,就像使用 setTimeout() 创建的那样。 delay 是任务添加到调度程序之前的最小时间量; 它可能更长


  • 执行顺序

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Prioritized Task Scheduling API</title>
  </head>
  <body>
    <strong>Prioritized Task Scheduling API</strong>
    <hr />
    <div class="result"></div>
    <input type="text" class="inp" autofocus />
    <script>
      // Prioritized Task Scheduling API

      // 提供了一种标准化的方法来优先处理属于应用程序的所有任务,无论它们是在网站开发人员的代码中定义的,还是在第三方库和框架中定义的
      // 任务优先级是非常粗粒度的,并且基于任务是否阻止用户交互或以其他方式影响用户体验,或者可以在后台运行
      // 基于 Promise 的,支持 设置和更改任务优先级、延迟添加到调度程序的任务、中止任务以及监视优先级更改和中止事件的能力
      // 在 window 和 worker 中都可用,使用全局对象上的 scheduler 属性

      // `Scheduler.postTask`: 接受一个回调函数(添加要调度的优先级任务)并返回一个 promise
      // 默认优先级 `user-visible` 的任务,该任务具有固定的优先级且无法中止
      // 共有三种优先级(从最高到最低排序):`user-blocking`、`user-visible`、`background`
      // `user-blocking`: 阻止用户与页面交互的任务。 这包括将页面呈现到可以使用的位置,或者响应用户输入
      // `user-visible`: 对用户可见但不一定阻止用户操作的任务。 这可能包括呈现页面的非必要部分,例如非必要的图像或动画。
      // `background`: 不是时间紧迫的任务。 这可能包括日志处理或初始化渲染不需要的第三方库。
      // `Scheduling.isInputPending`: 检查事件队列中是否有挂起的输入事件, 表明用户正在尝试与页面交互

      // 避免在用户主动与页面交互时阻塞主线程,从而提供更流畅的用户体验。然而,通过只在必要时让步,我们可以在没有用户输入需要处理时继续运行当前任务。这也避免了任务被放置在队列的后面,排在其他非必要的浏览器启动的任务之后,这些任务被安排在当前任务之后。

      // 任务优先级也可以从可选的第二个参数中传递给 `TaskSignal` 的 `postTask()` 中获取其初始值。 如果以这种方式设置,则可以使用与信号相关联的控制器来改变任务的优先级。
      // 注意:使用信号设置和更改任务优先级仅在未设置 `options.priority` 的 `postTask()` 参数,以及 `options.signal` 是 `TaskSignal`(而不是 `AbortSignal`)时有效。

      // 可以使用 `TaskController` 和 `AbortController` 以完全相同的方式中止任务。 唯一的区别是,如果您还想设置任务优先级,则必须使用 `TaskController`

      // 通过在 `options.delay` 的 `postTask()` 参数中指定整数毫秒数,可以延迟任务。 这有效地将任务添加到超时的优先级队列中,就像使用 `setTimeout()` 创建的那样。 `delay` 是任务添加到调度程序之前的最小时间量; 它可能更长

      scheduler.postTask(() => mylog('bckg 1'), { priority: 'background' });
      scheduler.postTask(() => mylog('usr-vis 1'), { priority: 'user-visible' });
      scheduler.postTask(() => mylog('usr-blk 1'), { priority: 'user-blocking' });

      scheduler.postTask(() => mylog('bckg 2'), { priority: 'background' });
      scheduler.postTask(() => mylog('usr-vis 2'), { priority: 'user-visible' });
      scheduler.postTask(() => mylog('usr-blk 2'), { priority: 'user-blocking' });

      scheduler.postTask(() => mylog('usr-vis 3 (default)'));

      /** @type {HTMLInputElement} */
      const inp = document.querySelector('.inp');
      window.addEventListener('mousemove', handleMouseMove);
      function handleMouseMove() {
        console.log('mousemove');
      }
      let timeoutID = setInterval(() => {
        const isPending = navigator.scheduling.isInputPending({ includeContinuous: true });
        console.log('isInputPending => ', isPending);
        if (isPending) {
          clearInterval(timeoutID);
          timeoutID = null;
          window.removeEventListener('mousemove', handleMouseMove);
        }
      }, 100);

      const result = document.querySelector('.result');
      function mylog(data) {
        result.innerHTML += data + '<br>';
      }
    </script>
  </body>
</html>
posted @ 2024-04-30 23:39  _clai  阅读(13)  评论(0编辑  收藏  举报