Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
This feature is not Baseline because it does not work in some of the most widely-used browsers.
協調的スケジューリングのバックグラウンドタスク API(バックグラウンドタスク API または requestIdleCallback() API とも呼ばれます)は、ユーザーエージェントが実行するための空き時間があると判断したときに自動的に実行されるタスクをキューに登録する機能を提供します。
メモ: この API はウェブワーカーでは利用できません。
ブラウザーのメインスレッドは、そのイベントループを中心に構成されています。このコードは、現在表示されている Document に対する保留中の更新を描画し、ページが実行する必要のある JavaScript コードを実行し、入力機器からのイベントを受け入れ、それらのイベントを受信する要素に配信します。さらに、イベントループはオペレーティングシステムとの対話、ブラウザー自身のユーザーインターフェイスの更新なども処理します。これは非常に忙しいコードの塊であり、メインの JavaScript コードもこれらすべてと一緒にこのスレッド内で実行される可能性があります。確かに、DOM に変更を加えることができるコードのほとんど(あるいはすべて)がメインスレッドで実行されているでしょう。なぜなら、ユーザーインターフェイスの変更はメインスレッドでのみ利用可能であることが一般的だからです。
イベント処理と画面の更新は、ユーザーがパフォーマンスの問題に気付く最も分かりやすい方法のうちの 2 つであるため、コードがウェブの良き市民であり、イベントループの実行の停滞を防ぐのに役立つことが重要です。過去には、可能な限り効率的なコードを書き、できるだけ多くの作業をワーカーに分担させること以外に、これを確実に行う方法はありませんでした。Window.requestIdleCallback() を使用すると、ブラウザーがシステムの遅延を引き起こすことなく、安全に使用できる時間をコードに伝えることができるようになるため、ブラウザーのイベントループがスムーズに実行されるように積極的に関与できるようになります。指定された制限内にとどまることで、ユーザー体験を大幅に向上させることができます。
アイドルコールバックは、システムを最大限に活用しつつ過負荷による遅延やその他のパフォーマンス問題を回避するため、コードがイベントループと連携する手段を提供することを目的としているため、その使用方法については慎重に検討すべきです。
バックグラウンドタスク API は、1 つの新しいインターフェイスのみを追加します。
IdleDeadlineアイドルコールバックに渡されるオブジェクトの型を表します。このオブジェクトは、コールバックが実行されるまでにどれだけの時間が残っているかを判断するためのメソッドと、コールバックがタイムアウトによって実行されているかどうかを判断するためのプロパティを提供します。
Window インターフェイスもこの API によって拡張され、新しい requestIdleCallback() および cancelIdleCallback() メソッドを提供します。
この例では、requestIdleCallback() を使用して、ブラウザーがアイドル状態になる時間に時間のかかる優先度の低いタスクを実行する方法を見ていきます。さらに、この例では、requestAnimationFrame() を使用して文書コンテンツの更新をスケジュールする方法も示しています。
以下では、この例の HTML と JavaScript のみを示します。CSS は、この機能を理解する上で特に重要ではないため、示されていません。
何を達成しようとしているのかを把握するために、HTML を見てみましょう。ここでは、操作の進行状況を表示するために使用されるボックス(id="container")と、テキスト出力を表示するために使用される 2 番目のメインボックス(id="logBox")が確立されています。
進捗ボックスは、進捗を表示するために <progress> 要素を使用し、進捗に関する数値情報を提示するために変更されるセクションを備えたラベルも使用しています。さらに、"Start" ボタン(ID が "startButton" と創造的に付けられています)もあり、ユーザーはこれを使用してデータ処理を開始します。
これで文書の構造が定義されたので、実際に作業を行う JavaScript コードを構築しましょう。目標は、関数を呼び出すリクエストをキューに追加できるようにし、システムが十分にアイドル状態になるたびにそれらの関数を実行するアイドルコールバックを備えたものにすることです。
これらの変数は、実行待ちのタスクのリストを管理するとともに、タスクキューとその実行に関する状態情報を管理するために使用されます。
次に、操作する必要があるいくつかの DOM 要素への参照を表す変数を用意します。 対象となる要素は次のとおりです。
最後に、他のアイテムのために 2 つの変数を用意します。
次に、実行が必要なタスクの管理方法を見ていきましょう。これを行うために、タスクの FIFO キューを作成し、アイドルコールバック期間中に時間が許す限り実行します。
タスクをキューに入れるまず、将来の実行のためにタスクをキューに入れる関数が必要です。その関数 enqueueTask() は次のようになります。
enqueueTask() は、入力として 2 つの引数を受け取ります。
タスクをキューに入れるには、taskList 配列にオブジェクトを追加します。オブジェクトには taskHandler と taskData の値が、それぞれ handler と data という名前で含まれています。次に、キューに入れられたタスクの総数を反映する totalTaskCount を増加させます(キューからタスクが削除されても減少させません)。
次に、アイドルコールバックがすでに作成されているかどうかを確認します。 taskHandle が 0 であった場合、アイドルコールバックがまだないことが分かりますので、 requestIdleCallback() を呼び出して作成します。runTaskQueue()、これは後ほど説明しますが、この関数を呼び出すように構成されており、timeoutは1秒に設定されているため、実際のアイドル時間がなくても、少なくとも1秒に1回は実行されるようになっています。
タスクの実行アイドルコールバックハンドラーである runTaskQueue() は、ブラウザーが作業を実行するのに十分なアイドル時間が確保されたと判断したとき、または 1 秒のタイムアウトが経過したときに呼び出されます。この関数の役割は、キューに登録されたタスクを実行することです。
runTaskQueue() の中心はループであり、残存時間(deadline.timeRemaining のチェックにより判定)が 0 より大きいことを確認できる限り、またはタイムアウト制限(deadline.didTimeout が真)となるか、タスクリストにタスクが残っている限り継続します。
キュー内の各タスクについて、実行する時間がある場合に以下の処理を行います。
時間が過ぎると、リストにまだタスクが残っている場合、再び requestIdleCallback() を呼び出して、次にアイドル時間が利用可能になったときにタスクの処理を続行できるようにします。キューが空の場合、taskHandle を 0 に設定して、スケジュールされたコールバックがないことを示します。これにより、次回 enqueueTask() が呼び出されたときにコールバックを要求する必要があることがわかります。
できるようになりたいことの 1 つは、ログ出力と進行状況情報で文書を更新することです。ただし、アイドルコールバック内から DOM を安全に変更することはできません。代わりに、requestAnimationFrame() を使用して、表示を更新するのに安全なときにブラウザーに呼び出してもらうようにします。
表示の更新のスケジュールDOM の更新は、scheduleStatusRefresh() 関数を呼び出すことでスケジュールされます。
これは単純な関数です。これは、statusRefreshScheduled の値を確認することで、すでに更新がスケジュールされているかどうかを確認します。これが false の場合、更新をスケジュールするために requestAnimationFrame() を呼び出し、updateDisplay() 関数を次のアニメーションフレームで呼び出すように指示します。
表示の更新updateDisplay() 関数は、進捗ボックスとログ出力の中身を描画する責任があります。これは、次のフレームのレンダリング処理中に変更を適用しても安全な状態にある DOM に対して、ブラウザーによって呼び出されます。
まず、ログ内のテキストが最下部までスクロールされた場合、scrolledToEnd が true に設定されます。それ以外の場合は false に設定されます。この値を用いて、ログへのコンテンツ追加完了後もログが最下部に表示されるよう、スクロール位置を更新すべきかどうかを判断します。
次に、タスクがキューに追加された場合、進捗状況とステータス情報を更新します。
それから、ログへの追加を待っているテキストがある場合(すなわち、logFragment が null でない場合)、Element.appendChild() を使用してそれをログ要素に追加し、logFragment を null にリセットして、再び追加されないようにします。
log() 関数は指定されたテキストをログに追加します。log() が呼び出された時点で、直ちに DOM を操作しても安全かどうかがわからないため、ログテキストは更新が安全になるまでキャッシュされます。上記の updateDisplay() のコード内では、アニメーションフレームの更新時にログテキストを実際にログ要素に追加する処理を確認できます。
まず、logFragment という名前の DocumentFragment オブジェクトが存在しない場合は、それを作成します。この要素は擬似 DOM であり、メインの DOM 自体を直ちに変更することなく要素を挿入できます。
次に、新しい <div> 要素を作成し、その内容を入力された text と一致するように設定します。 それから、その要素を logFragment の擬似 DOM の末尾に追加します。 logFragment は、DOM が変更の準備が整い、次に updateDisplay() が呼び出されるまでログ項目を蓄積します。
タスク管理と表示保守のコードが完成したので、実際に作業を実行するタスクを実行するコードの設定を始められます。
タスクハンドラーとして使用する関数、つまりタスクオブジェクトの handler プロパティの値として使用される関数は logTaskHandler() です。これは各タスクごとにログに様々な情報を出力する単純な関数です。実際のアプリケーションでは、このコードをアイドル時間中に実行したい任意のタスクに置き換えてください。ただし、DOM を変更する操作はすべて requestAnimationFrame() を介して処理する必要がある点に注意してください。
ユーザーが開始ボタンをクリックすると、すべての処理が開始され、decodeTechnoStuff() 関数が呼び出されます。
decodeTechnoStuff() はまず、totalTaskCount(これまでにキューに追加されたタスクの数)と currentTaskNumber(現在実行中のタスク)の値をゼロにリセットし、その後 updateDisplay() を呼び出して表示を「まだ何も起きていない」状態にリセットします。
この例では、ランダムな数のタスク(100 ~ 200 個)を作成します。そのために、Math.random() のドキュメントで例として提供されているgetRandomIntInclusive() 関数を使用して、作成するタスクの数を取得します。
それから、実際にタスクを作成するループを開始します。各タスクについて、taskData というオブジェクトを作成します。このオブジェクトには 2 つのプロパティが含まれています。
各タスクは、enqueueTask() を呼び出してキューに追加されます。この際、ハンドラー関数として logTaskHandler() を、関数が呼び出された際に渡すオブジェクトとして taskData オブジェクトを渡します。
以下のコードは、上記のコードが実際に動作した結果です。ブラウザーの開発者ツールで試してみてください。自分のコードで活用する方法を試してみてください。
| requestIdleCallback() # the-requestidlecallback-method |
Enable JavaScript to view this browser compatibility table.
This page was last modified on 2025年11月24日 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.