DeferredTask.jsm

Firefox 28 における注記

Firefox 28 でインターフェースの変更があり、古いメソッドは削除されました。

DeferredTask.jsm JavaScript コードモジュールは、遅延後に実行するタスクのためのユーティリティルーチンを提供します。遅延前に実行が試みられる複数の同じタスクは一本化されます。このモジュールを使用するには、先にコードモジュールをあなたの JavaScript スコープにインポートしておく必要があります:

Components.utils.import("resource://gre/modules/DeferredTask.jsm");

このモジュールは、例えば、ファイルにデータを書き込み、そのすぐ後に再びデータを書き込む可能性がある場合に使用できます。DeferredTask でタスクに数ミリ秒間の遅延を起こし、データへの新しい変更をその間に行ってください。

  • データの最終バージョンのみが実際に書き込まれます。
  • 他の変更を考慮していくらかの猶予の遅延が追加されます。

Gecko 18.0 が必要(Firefox 18.0 / Thunderbird 18.0 / SeaMonkey 2.15 / Firefox OS 1.0.1)

DeferredTask コンストラクタ

2 秒間遅らせたい関数呼び出しがある場合、DeferredTask コンストラクタを使用して次のようにしてください:

var task = new DeferredTask(myFunction, 2000);

Firefox 28 第一引数にはジェネレータ関数を渡す事もできます。

メソッドの概要

bool isPending(); 廃止 Gecko 28.0
void start(); 廃止 Gecko 28.0
void flush(); 廃止 Gecko 28.0
void cancel(); 廃止 Gecko 28.0
void arm(); Gecko 28.0 が必要
void disarm(); Gecko 28.0 が必要
Promise finalize(); Gecko 28.0 が必要

属性

isArmed boolean このタスクが開始を要求されているかどうかを表します。この値はタスクが現在実行中であるかどうかとは関係ありません。 Gecko 28.0 が必要
isRunning boolean このタスクが現在実行中であるかどうかを表します。タスクの関数内からこの値を取得した場合常に true ですが、タスクが非同期のジェネレータ関数の場合、外部のコードから取得しても true です。 Gecko 28.0 が必要

メソッド

isPending

廃止 Gecko 28.0

現在のタスク状態を確認します。

bool isPending();
戻り値

未実行の場合は true、そうでない場合は false を返します。

start

廃止 Gecko 28.0

タスクを開始 (または延期) します。

void start();

flush

廃止 Gecko 28.0

延期したタスクをすぐに実行します。

void flush();

cancel

廃止 Gecko 28.0

未実行のタスクをキャンセルします。

void cancel();

arm

Gecko 28.0 が必要

タスク構築時に指定した遅延の後、タスクを実行する事を要求します。複数回の呼び出しは追加の遅延を引き起こしません。タスクが実行中である場合、現在の実行の終了後から遅延が開始されます。

タスク構築時に遅延が 0 に指定されていたとしても、タスクは常にイベントループの異なる瞬間に実行されます。イベントループ中の同じ瞬間における複数回の "arm" の呼び出しは、一回のタスクの実行となる事が保証されます。

設計では、このメソッドは呼び出し側に対し、次の実行がいつ終了するかを検出する手段や結果を取得する手段を提供しません。実際、これを行う事は往々にして重複処理やログ取得となります。タスクの完了時に特殊な処理やエラーログが必要であれば、タスク中で try/catch/finally 節等を用いてタスク自身が行う方が良いでしょう。"finalize" メソッドは一般的にはシャットダウン時に完了を待つ時に使われます。

void arm();

disarm

Gecko 28.0 が必要

このタスクの遅延された実行の要求をキャンセルします。ただし既に実行中のタスクはキャンセルできません。

このメソッドは現在実行中のタイマーを停止させます。このため、再度 "arm" メソッドを呼び出した場合、遅延はタスク構築時に指定された元の値から開始されます。

void disarm();

finalize

Gecko 28.0 が必要

保留中のタスクを即座に実行し、最後まで実行される事を保証します。これ以降のタイマーの開始要求は阻止されます。

  • もしタスクが実行中で、タイマーの開始が要求されている場合、現在のタスクの実行が完了した直後、即座にもう一度タスクが実行され、この後に返り値の promise が解決します。
  • もしタスクが実行中で、タイマーの開始が要求されていない場合、返り値の promise は現在の実行が完了した時に解決されます。
  • もしタスクが実行中ではなく、タイマーの開始が要求されている場合、タスクが即座に開始され、返り値の promise はこの新しい実行が完了した時に解決されます。
  • もしタスクが実行中ではなく、タイマーの開始も要求されていない場合、このメソッドは解決済みの promise を返します。
Promise finalize();

Firefox 28 における注記

この節は Firefox 28.0 以降の DeferredTask.jsm について書かれています。

指定された遅延の後に実行される関数または非同期のタスクを作成します。遅延が経過する前の複数回の "arm" メソッド呼び出しは結合されます。タスクは実行中に再入する事はできませんが、前回の実行が完了した後で再度実行する事はできます。

 

一般的な使用例は、短期間における複数回の非同期呼び出しによってデータが変更され、その度にファイルに保存しなければいけない場合です。

let saveDeferredTask = new DeferredTask(function* () {
  yield OS.File.writeAtomic(...);
  // 補足されない例外は報告されます
}, 2000);

// このタスクは準備完了ですが、要求されるまで実行はされません

"arm" メソッドは、タスクを実行する内部タイマーを開始するのに使用します。複数回の "arm" の呼び出しは追加の遅延を引き起こしません。

saveDeferredTask.arm();

// タスクはこの時点から 2 秒後に実行されます

yield waitOneSecond();
saveDeferredTask.arm();

// タスクはこの時点から 1 秒後に実行されます

タイマーは遅延をリセットするため、もしくは単純に実行をキャンセルするために解除できます。

saveDeferredTask.disarm();
saveDeferredTask.arm();

// タスクはこの時点から 2 秒後に実行されます

指定時間が経過し内部タイマーが発動するとタスクの実行が開始され、このタスクはこれ以降キャンセルできなくなります。しかし、タスクの実行中にタイマーの開始を再び要求する事は可能であり、この場合タイマーが実際に開始するには前のタスクが完了する必要があります。このため、タスクの実行と実行の間の休止時間は指定された遅延以上である事が保証されます。

"finalize" メソッドはタスクが確実に終了する事を保証するために使用できます。このメソッドが返した promise はタスクの最後の実行が完了した時に解決されます。タスクの実行が最後である事を保証するために、このメソッドは以降の "arm" メソッドの呼び出しによるタイマーの開始要求を拒否します。

"finalize" メソッドが呼び出された時点でタイマーが既に開始されていた場合、タスクは即座に実行されます。この時点でタスクが既に実行されていた場合、現在の実行が終了し次第、即座に最後の実行が始めから終わりまで再び行なわれます。もしタイマーの開始が要求されていなかった場合、"finalize" メソッドは実行中のタスクが完了する事を保証します。

例えばシャットダウン中に、もしタイマーの開始が要求されていた場合、最新バージョンのデータを用いた保留中の書き込みが処理される事を保証したいでしょう。

AsyncShutdown.profileBeforeChange.addBlocker(
  "Example service: shutting down",
  () => saveDeferredTask.finalize()
);

しかし、どのみち保存されたデータをディスクから削除しようとしている場合、むしろ保留されている書き込みの開始を抑制した方が良いでしょう。ただし、削除しようとしているファイルが使用中ではなくなるように、現在処理中の書き込みが終了する事は保証した上で。

saveDeferredTask.disarm();
saveDeferredTask.finalize().then(() => OS.File.remove(...))
                           .then(null, Components.utils.reportError);

Document Tags and Contributors

Contributors to this page: Marsf, arai
最終更新者: arai,