requestIdleCallback()

バックグラウンドタスクの協調的スケジューリング

W3C ワーキングドラフト

このドキュメントの詳細
このバージョン:
https://www.w3.org/TR/2025/WD-requestidlecallback-20250521/
最新公開バージョン:
https://www.w3.org/TR/requestidlecallback/
最新エディタードラフト:
https://w3c.github.io/requestidlecallback/
履歴:
https://www.w3.org/standards/history/requestidlecallback/
コミット履歴
実装レポート:
https://wpt.fyi/requestidlecallback
編集者:
Scott Haseley (Google Inc.)
以前の編集者:
Ross McIlroy (Google Inc.)
Ilya Grigorik (Google Inc.)
フィードバック:
GitHub w3c/requestidlecallback (プルリクエスト, 新しい課題, オープン課題)

概要

本書は、ウェブページの作成者が、同じイベントループを共有する他の高優先度タスク(入力処理、アニメーション、フレーム合成など)に遅延を発生させることなく、協調的にバックグラウンドタスクをスケジューリングできるAPIを定義します。ユーザーエージェントは、現在スケジュールされているタスク、vsyncの締め切り、ユーザーインタラクションなどの知識をもとに、ユーザーに知覚される遅延やアニメーションのカクつき、入力応答の悪化を発生させずにバックグラウンドタスクを実行するタイミングを、より適切に判断できます。そのため、このAPIを使用することで、ブラウザがアイドル状態となる時間帯にバックグラウンドタスクのより適切なスケジューリングが実現されます。

この文書のステータス

このセクションでは、本書の発行時点でのステータスについて説明します。現在のW3C発行物と本技術レポートの最新版は、 W3C標準とドラフト一覧(https://www.w3.org/TR/)でご覧いただけます。

Web Performance Working Group は仕様用のテストスイートを管理しています。ワーキンググループの実装レポートもご参照ください。本ドキュメントの実装に関心のあるベンダーは、下記のメーリングリストに参加し、議論に加わることを推奨します。

この文書はWeb Performance Working Groupにより、勧告トラックを使用してワーキングドラフトとして公開されました。

ワーキングドラフトとしての公開は、W3Cおよびその会員による承認を意味しません。

この文書はドラフトであり、今後いつでも他の文書によって更新・差し替え・廃止される可能性があります。進行中の作業以外の文書として引用するのは適切ではありません。

このドキュメントは、W3C特許ポリシーのもとで活動するグループにより作成されました。 W3C は、グループの成果物に関連してなされた特許開示の公開リストを管理しています。そのページには特許開示の手順も掲載されています。特許について実際に知っている人は、Essential Claim(s)を含むと考えた場合、W3C特許ポリシーの第6節に従って情報を開示する必要があります。

この文書は 2023年11月3日付けW3Cプロセス文書に従って管理されています。

1. はじめに

このセクションは規範的ではありません。

ウェブページは、時間的に重要ではないものの、実行にかなりの時間がかかる可能性がある計算タスクを、ブラウザのイベントループで実行したい場合がよくあります。そのようなバックグラウンドタスクの例として、アナリティクスデータの記録、長時間かかるデータ処理操��、クライアントサイドのテンプレート処理や、近い将来表示される可能性が高いコンテンツのプリレンダリングなどが挙げられます。これらのタスクは、入力への反応やrequestAnimationFrame() を使ったスクリプトベースのアニメーションなど、他の時間的に重要な処理とイベントループを共有しなければなりません。これらのバックグラウンドタスクは、通常、setTimeout() でコールバックをスケジューリングし、そのコールバック内でバックグラウンドタスクを実行することで行われます。

この方法の欠点は、スクリプトの作成者が、あるsetTimeout() コールバックが時間的に重要なのか、それともブラウザがアイドル状態になるまで遅延してもよいものなのかをユーザーエージェントに伝える方法がないことです。さらに、ユーザーエージェントは、コールバックが時間的に重要な処理を遅延させたり、カクつきなどのユーザが気づく遅延を引き起こさずに、どの程度の時間まで実行し続けられるかの情報をコールバックに提供できません。その結果、もっとも簡単な対応策は、setTimeout() を非常に小さな値で呼び出し、そこで最小限の作業を実行し、さらに必要な作業をsetTimeout() でもう一度スケジューリングすることです。しかしこの方法は、ユーザーエージェントのイベントループに複数の小さいタスクを投稿してその実行をスケジューリングする余分なオーバーヘッドが発生します。また、各コールバックの合間にユーザーエージェントが他の時間的に重要な処理を適切に割り込ませる必要があるため、各コールバックの実行にかかる時間をユーザーエージェントが正確に推測できない点も問題です。

本書で解説するAPIは、スクリプト作成者が、ユーザーエージェントがアイドル状態であるときにコールバックのスケジューリングをリクエストできるようにします。ユーザーエージェントは、どれくらいアイドル状態が続くと見積もっているかを、コールバックに渡される期限(deadline)として提供します。ページ作成者はこの期限を使って、これらのバックグラウンドタスクがアニメーションや入力応答などの遅延が許されないイベントに影響を与えないようにできます。

以下はこのAPIを使ってバックグラウンドタスクを書く例です。

<!DOCTYPE html>
<title>requestIdleCallbackを使用したバックグラウンドタスクのスケジューリング</title>
<script>
var requestId = 0;
var pointsTotal = 0;
var pointsInside = 0;

function piStep() {
  var r = 10;
  var x = Math.random() `*` r `*` 2 - r;
  var y = Math.random() `*` r `*` 2 - r;
  return (Math.pow(x, 2) + Math.pow(y, 2) < Math.pow(r, 2))
}
function refinePi(deadline) {
  while (deadline.timeRemaining() > 0) {
    if (piStep())
      pointsInside++;
    pointsTotal++;
  }
  currentEstimate = (4 `*` pointsInside / pointsTotal);
  textElement = document.getElementById("piEstimate");
  textElement.innerHTML="円周率推定値: " + currentEstimate;
  requestId = window.requestIdleCallback(refinePi);
}
function start() {
  requestId = window.requestIdleCallback(refinePi);
}
function stop() {
  if (requestId)
    window.cancelIdleCallback(requestId);
  requestId = 0;
}
</script>
<button onclick="start()">クリックで開始</button>
<button onclick="stop()">クリックで停止</button>
<div id="piEstimate">未開始</div>

2. アイドル期間

このセクションは規範的ではありません。

入力処理、描画や合成など、そのフレームの処理が完了したあと、ユーザーエージェントのメインスレッドは次のいずれかのタイミングまでしばしばアイドル状態になります:次のフレーム処理の開始、未処理のタスクが実行可能になる、またはユーザー入力がある場合です。本仕様は、こうしたアイドル時間にrequestIdleCallback() APIを 使ってコールバックの実行をスケジューリングする方法を提供します。

requestIdleCallback() API 経由で投稿されたコールバックは、ユーザーエージェントが定義したアイドル期間中に実行対象となります。アイドルコールバックが実行されると、その時のアイドル期間の終了時点に対応する期限(deadline)が渡されます。アイドル期間がいつかはユーザーエージェントごとに定義されますが、一般的にはブラウザがアイドル状態になる静穏時に発生することが期待されます。

アイドル期間の一例は、アクティブなアニメーション中に特定のフレームを画面にコミットした後、次のフレームの処理を開始するまでの間で、1で示されています。こうしたアイドル期間は、アクティブなアニメーションや 画面更新中に頻繁に発生しますが、通常ごく短時間(たとえば60Hzのvsyncサイクルのデバイスでは16ms未満)です。

フレーム間アイドル期間の例
1 フレーム間アイドル期間の例
注記

ウェブ開発者は、アイドルコールバック中に実行するすべての作業を考慮しておくべきです。Promiseの解決やページレイアウトの発生など、一部の操作は、アイドルコールバック終了後に後続のタスクをスケジューリングする場合があります。このような場合、次のフレーム締め切り前にこれらの操作が実行できるよう、期限満了前に(コールバック側が)処理を明け渡すことで追加作業に対応させるべきです。

アイドル期間の別の例として、ユーザーエージェントがアイドルで、画面更新が発生していないときがあります。このような場合、ユーザーエージェントはアイドル期間の終了を制約できる後続タスクを持たないことがあります。予測不能なタスク(たとえばユーザー入力処理など)による、ユーザが気づく遅延を回避するため、こうしたアイドル期間の長さは最大値50msに制限すべきです。アイドル期間が終了してもユーザーエージェントが引き続きアイドルであれば、2のように、追加のアイドル期間をスケジューリングし、長いアイドル時間帯でもバックグラウンド処理が続けて行えるようになります。

未処理のフレーム更新がないときのアイドル期間例
2 未処理のフレーム更新がないときのアイドル期間例

アイドル期間中、ユーザーエージェントはFIFO順でアイドルコールバックを実行し、アイドル期間終了または実行待ちのコールバックがなくなるまで繰り返します。そのため、すべてのアイドルコールバックが一つのアイドル期間中に必ずしも実行されるとは限りません。残ったアイドルタスクは次のアイドル期間で実行対象になります。

注記

性能を最大限に発揮するため、開発者は意味のないコールバック(例えばrequestAnimationFrameやsetTimeout等)を不要に残さず、イベント対応が必要になった時点でのみスケジューリングしてください。このパターンは全体の効率を高め、ユーザーエージェントがバックグラウンド作業に効率的に使える長いアイドルコールバック(最大50ms)のスケジューリングを実現します。

現在のアイドル期間の開始前に投稿されたタスクだけがその期間中に実行対象となります。そのため、アイドルコールバック中にrequestIdleCallback() でもうひとつコールバックを投稿した場合、その後続コールバックは今のアイドル期間中には実行されません。これにより、アイドルコールバックが期限までに処理を終えられない場合、将来のアイドル期間に自身を再投稿するコードパターン(下記例のような)が可能になります――このとき短すぎるアイドル期間中にコールバックが何度も実行されてしまうことはありません:

function doWork(deadline) {
  if (deadline.timeRemaining() <= 5) {
    // これには5ms以上かかるので、
    // 十分長い締め切りで次回呼ばれるのを待つ。
    requestIdleCallback(doWork);
    return;
  }
  // 処理を行う...
}

次のアイドル期間の開始時、新たに投稿されたアイドルコールバックは実行可能なタスクリストの末尾に追加されます。これにより、コールバックの再投稿はラウンドロビン方式で実行されることが保証され、すべてのコールバックが先行するタスクの再投稿コールバックよりも先に一度は実行されることになります。

注記

本仕様の将来バージョンでは他のスケジューリング戦略も認められる可能性があります。たとえば「同じアイドル期間中にスケジュール」「アイドル時間がXミリ秒以上の期間中」等。現行仕様では次のアイドル期間へのスケジューリングだけをサポートしており、その際にコールバックがロジックを実行するか、さらに再投稿で次のアイドル期間への移行ができます。

ユーザーエージェントがウェブページをユーザ不可視と判断した場合、デバイスの電力消費を減らすためにアイドル期間を間引くことがあります。例として、連続ではなく10秒ごとに一回だけアイドル期間を呼び出すなどです。

最後に注意すべき点として、ページの負荷が高い場合、ユーザーエージェントがアイドルCPU時間を全く確保できない場合もあります。そのため、requestIdleCallback() API経由で投稿されたアイドルコールバックは、無期限に実行が延期される可能性があり、その場合アイドル期間自体がスケジューリングされないこともあります。コールバックをアイドル期間中に実行したいものの、実行期限を設けておきたい場合には、options引数のtimeoutプロパティを指定できます。指定したタイムアウトが先に到達した場合は、アイドル期間外でもタスクがキューイングされて実行されます。

注記

最大50msという期限値は、研究 [RESPONSETIME]に基づいています。これによれば、ユーザー入力に100ms以内に応答すると、人間にはほぼ瞬時に反応したと認識されます。アイドル期限を50msに制限することで、仮にアイドルタスクが開始直後にユーザー入力があった場合でも、ユーザーエージェントはその入力に50ms以内で反応できるため、遅延が知覚されません。

3. 適合性

「規範的ではありません」と記されたセクションだけでなく、本仕様中のすべての著述ガイドライン、図、例、注記も規範的ではありません。この仕様のその他全ては規範的です。

このドキュメント中のキーワードMUSTREQUIREDSHALLSHOULD は、 BCP 14 [RFC2119] [RFC8174] に記載されている通りに解釈してください。ただし、例示のようにすべて大文字で出てきた場合(のみ)。

本仕様中のIDL断片は、準拠IDL断片に必要な形式としてMUST解釈されます。

この仕様で定義される適合クラスは一つだけです:

準拠ユーザーエージェント
本仕様におけるMUSTREQUIREDSHALL要件すべてを満たす場合、ユーザーエージェントは準拠ユーザーエージェントと見なされます。準拠ユーザーエージェントは、IDL断片の準拠実装4. Windowインターフェース拡張参照)でもなければなりません。

4. Window インターフェース拡張

以下のIDL断片の partial interface は、 requestIdleCallback() 操作を Window オブジェクト上に公開するために使用されます。

WebIDLpartial interface Window {
  unsigned long requestIdleCallback(IdleRequestCallback callback, optional IdleRequestOptions options = {});
  undefined cancelIdleCallback(unsigned long handle);
};

dictionary IdleRequestOptions {
  unsigned long timeout;
};

[Exposed=Window] interface IdleDeadline {
  DOMHighResTimeStamp timeRemaining();
  readonly attribute boolean didTimeout;
};

callback IdleRequestCallback = undefined (IdleDeadline deadline);

Window は以下を持つ:

4.1 requestIdleCallback() メソッド

requestIdleCallback(callback, options)IdleRequestCallback および省略可能な IdleRequestOptions で呼び出されたとき、ユーザーエージェントは 次の手順を実行しなければならない:

  1. window を this の Window オブジェクトとする。
  2. windowアイドルコールバック識別子 を1インクリメントする。
  3. handlewindowアイドルコールバック識別子 の現在の値とする。
  4. callbackwindowアイドルリクエストコールバックのリストの末尾に、handleに関連付けて追加する。
  5. handle を返し、それからこのアルゴリズムを非同期に続行する。
    注記

    以下の手順は並列に実行され、省略可能な timeout プロパティが指定された場合 setTimeout() に似たタイマーがキューされる。ここから、アイドルとタイムアウト両者のコールバックはレース状態となり、 一方が先にスケジュールされれば他方をキャンセルする(例: アイドルコールバックが先にスケジュールされた場合はタイムアウトコールバックがキャンセルされ、その逆も同様)。

  6. timeout プロパティが options に存在し値が正の場合:
    1. timeout ミリ秒間待つ。
    2. このアルゴリズムのそれまでに投稿された timeout を加算した時刻が本件より前であるすべての呼び出しの完了を待つ。
    3. 必要に応じ、ユーザーエージェント定義のさらに追加の時間待ってもよい。
      注記

      これは省電力のため、ユーザーエージェントが必要に応じてタイムアウトをパディングできるよう意図されたもの。 たとえば一部のプロセッサは低消費電力モード時にタイマーの粒度が粗くなるため、こうしたプラットフォームでは 高精度タイマーによる消費増大を避けるため、ユーザーエージェントはタイマーを遅延させてもよい。

    4. アイドルタスク用の タスクソース に紐づくキューで アイドルコールバックタイムアウトアルゴリズムhandlewindow を渡してキューイングする。
注記

requestIdleCallback() は単一のコールバックだけをスケジューリングし、単一の アイドル期間中に実行される。コールバックが指定期限までに処理を終えられない場合は、 (コールバック内部で)再度 requestIdleCallback() を呼び出して続きを将来のコールバックとしてスケジューリングし、すぐに処理を抜けて イベントループ に制御を返すべきである。

4.2 cancelIdleCallback() メソッド

cancelIdleCallback() メソッドは、以前スケジューリングをリクエストしたアイドルコールバックをキャンセルするためのものである。 cancelIdleCallback(handle) が呼ばれたとき、ユーザーエージェントは次の手順を実行しなければならない:

  1. window を this の Window オブジェクトとする。
  2. windowアイドルリクエストコールバックのリスト または 実行可能なアイドルコールバックのリスト のうちで handle に紐付くエントリを探す。
  3. 該当するエントリが存在すれば、そのエントリを両方のリストから取り除く。
注記

cancelIdleCallback() は、windowアイドルリクエストコールバックのリスト または 実行可��なアイドルコールバックのリスト のエントリに対して呼ばれることがある。いずれの場合もそのエントリはリストから削除され、コールバックは実行されない。

4.3 IdleDeadline インターフェース

IdleDeadline には 期限時刻の取得アルゴリズム が関連付けられており、 これは期限となる絶対時刻(ミリ秒単位)の DOMHighResTimeStamp を返す。 初期値はゼロになる。

timeRemaining() メソッドが IdleDeadline オブジェクトで呼ばれた場合、 期限切れまでの残り時間を DOMHighResTimeStamp で返さなければならない。この値は計測可能だがタイミング攻撃を防止できる程度にせよ ― 詳細は [HR-TIME] の「Privacy and Security」を参照。この値は以下の手順で計算:

  1. nowDOMHighResTimeStamp 型で現在の高解像度時刻(ミリ秒)として取得する。
  2. deadline は、IdleDeadline期限時刻の取得アルゴリズム の結果とする。
  3. timeRemainingdeadline - now とする。
  4. timeRemaining が負なら 0 にする。
  5. timeRemaining を返す。

IdleDeadline には timeout が関連付けられ、初期値は false である。 didTimeout ゲッターは必ず timeout を返す。

注記

アイドルコールバックタイムアウトアルゴリズムtimeout を true にし、これは登録時に渡された IdleRequestOptions のタイムアウトプロパティ値超過により アイドル期間外でコールバックが実行されることを示す。

5. 処理

5.1 アイドル期間開始アルゴリズム

アイドル期間を開始するには、Window windowgetDeadlineDOMHighResTimeStamp を返すアルゴリズム)を与えて行う:[HR-TIME]

注記

このアルゴリズムは イベントループ処理モデル により、イベントループが アイドルであると判断したときに呼び出される。

  1. ユーザーエージェントがアイドル期間を遅延すべきと判断した場合は、オプションでこのアルゴリズムからリターンしてよい。
    注記

    これはユーザーエージェントが必要に応じてデバイスの省電力最適化のため、アイドル期間の開始を遅らせられるようにする意図です。たとえば、Documentvisibility state が "hidden" の場合は、ユーザーエージェントはアイドル期間生成を間引き、 たとえば10秒に1度だけアイドル期間を発生させて省電力最適化を行うことができる。

  2. pending_listwindowアイドルリクエストコールバックのリストとする。
  3. run_listwindow実行可能アイドルコールバックのリストとする。
  4. pending_listの全エントリを順序を保ったままrun_listの末尾に追加する。
  5. pending_listをクリアする。
  6. アイドルタスク用タスクを、 task source に紐づくキューにキューイングし、パラメータとしてwindowgetDeadlineを用いて アイドルコールバック呼び出しアルゴリズム のステップを実行する。
注記

現在から期限(deadline)までの時間をアイドル期間という。同じWindow につきアクティブなアイドル期間は同時に1つしか存在しない。ユーザーエージェントはアイドルでなくなったと判断した時点で このアイドル期間を早期終了でき、その場合次のアイドル期間はdeadlineより後にしか始まらない。

5.2 アイドルコールバック呼び出しアルゴリズム

アイドルコールバック呼び出しアルゴリズムWindow windowgetDeadlineDOMHighResTimeStamp を返すアルゴリズム)で行う:[HR-TIME]。

  1. ユーザーエージェントが新たに高優先度な作業がスケジューリングされたなどの理由でアイドル期間を早期終了すべきだと判断した場合、このアルゴリズムからリターン。
  2. nowを現在時刻にする。
  3. nowgetDeadlineの呼び出し結果より小さく、かつ window実行可能アイドルコールバックのリストが空でなければ:
    1. window実行可能アイドルコールバックのリストから 先頭のcallbackをpopする。
    2. IdleDeadline を生成し、その期限時刻の取得アルゴリズムをgetDeadline にする。このdeadlineArgを用意する。
    3. コールバック関数の呼び出しcallbackを « deadlineArg » , "report"を引数に呼び出す。
    4. window実行可能アイドルコールバックのリスト が空でなければ、タスクをキューイングし、 パラメータにはgetDeadlinewindowを使い、本アルゴリズムの残りステップを実行してリターン
注記

ユーザーエージェントは、たとえdeadlineに達していなくても、ステップ1のリターンでアイドル期間を早期終了してよい。 たとえば高優先度作業が実行可能になった場合などで判断される。

5.3 アイドルコールバックタイムアウト実行アルゴリズム

アイドルコールバックタイムアウトアルゴリズム:

  1. callback を、 windowアイドルリクエストコールバックのリストまたは実行可能なアイドルコールバックのリストから、 このアルゴリズムのhandle引数に対応するエントリとして探索する。
  2. callbackがundefinedでない場合:
    1. callbackwindowアイドルリクエストコールバックのリスト実行可能なアイドルコールバックのリストの両方から削除する。
    2. now を現在時刻にする。
    3. IdleDeadline の新しいインスタンスdeadlineArgを用意し、期限時刻取得にはnowを返すアルゴリズムを設定し、 timeoutもtrueに設定する。
    4. コールバック関数の呼び出しcallbackを « deadlineArg » , "report"を引数に呼び出す。

6. プライバシーに関する考慮事項

アイドルコールバックをスケジューリングすると、ユーザーエージェントはどのくらいアイドル状態で居��けるつもりかの推定値を提供する。この情報は、そのフレーム内で他のアプリタスクやブラウザー処理にかかる時間を推定するのに利用できる。ただし、開発者はすでに他の手段(たとえばrequestAnimationFrameでフレームの開始をマークし、次のフレーム時刻を推定してあらゆるコールバック内で「残り時間」を計算するなど)で得ることは可能である。

IdleDeadlineインターフェースで返すこの時間推定値の精度は、 キャッシュや統計的フィンガープリント攻撃への対策として、coarsen timecross-origin isolated capability 基準で粗くすることで、このAPIが他のタイマーAPI以上の情報を公開しないようにすべきである。 [HR-TIME]

7. セキュリティに関する考慮事項

TBD

A. 謝辞

編集者は、本仕様への貢献者として以下の方々に謝意を表します: Sami Kyostila, Alex Clarke, Boris Zbarsky, Marcos Caceres, Jonas Sicking, Robert O'Callahan, David Baron, Todd Reifsteck, Tobin Titus, Elliott Sprehn, Tetsuharu OHZEKI, Lon Ingram, Domenic Denicola, Philippe Le Hegaret and Anne van Kesteren.

B. 参考文献

B.1 規範的参考文献

[HR-TIME]
High Resolution Time. Yoav Weiss. W3C. 2024年11月7日. W3C 作業草案. URL: https://www.w3.org/TR/hr-time-3/
[html]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. リビングスタンダード. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997年3月. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. 2017年5月. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[webidl]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. リビングスタンダード. URL: https://webidl.spec.whatwg.org/

B.2 参考情報

[dom]
DOM Standard. Anne van Kesteren. WHATWG. リビングスタンダード. URL: https://dom.spec.whatwg.org/
[RESPONSETIME]
Response time in man-computer conversational transactions. Robert B. Miller. 1968年12月. Fall Joint Computer Conference. URL: http://yusufarslan.net/sites/yusufarslan.net/files/upload/content/Miller1968.pdf