LockManager: request() メソッド
Baseline
広く利用可能
この機能は広く実装されており、多くのバージョンの端末やブラウザーで動作します。2022年3月以降、すべてのブラウザーで利用可能です。
LockManager インターフェイスの request() メソッドは、名前と性質を指定する引数をとり、Lock オブジェクトを要求します。要求された Lock はコールバックに渡されます。この関数自体は、ロックの解放後にコールバックの結果で解決 (または拒否) され、リクエストが中止された場合は拒否される Promise を返します。
引数 options のプロパティ mode は、"exclusive" と "shared" のいずれかをとることができます。
一度に 1 個のコードインスタンスのみがロックを確保するべきときは、"exclusive" ロックを要求します。これはタブで実行するコードにもワーカーで実行するコードにも当てはまります。これはリソースへの互いに排他的なアクセスを表します。ある名前の "exclusive" ロックが確保されているときは、同じ名前の他のロックは一切確保できません。
コードの複数のインスタンスがリソースへのアクセスを共有できるときは、"shared" ロックを要求します。ある名前の "shared" ロックが確保されているときは、同じ名前の他の "shared" ロックを獲得することはできますが、その名前の "exclusive" ロックを獲得・確保することができません。
この共有 / 排他ロックのパターンは、読み込みは同時に複数 (それぞれが "shared" ロックを要求する) 行うことを許し、書き込みは 1 個だけ (単一の "exclusive" ロック) 許すなど、データベースのトランザクションのアーキテクチャではよくみられます。これは readers-writer パターンとして知られています。IndexedDB API では、これは同じ意味の "readonly" および "readwrite" トランザクションとして公開されています。
構文
request(name, callback)
request(name, options, callback)
引数
name-
要求するロックの識別子です。
options省略可-
生成するロックの性質を記述するオブジェクトです。以下の値が有効です。
mode省略可-
"exclusive"または"shared"です。デフォルト値は"exclusive"です。 ifAvailable省略可-
trueに設定した場合、ロックが既に確保されていない場合のみロックを獲得できます。ロックを獲得できない場合は、コールバックにはLockのインスタンスではなくnullが渡されます。デフォルト値はfalseです。 steal省略可-
trueに設定した場合、同じ名前の既に確保されているロックはすべて解放され、待機中のすべての要求よりも優先してロックを獲得します。デフォルト値はfalseです。警告: 使用には注意が必要です! これまでロック内で実行されていたコードの実行は継続し、新しくロックを確保したコードと衝突する可能性があります。
signal省略可-
AbortSignal(AbortControllerのsignalプロパティ) です。指定され、対応するAbortControllerが中断された場合、獲得できていないロックの要求は破棄されます。
callback-
ロックを獲得したとき呼び出されるメソッドです。ロックはコールバックから返ったとき (または例外が投げられたとき) 自動的に解放されます。通常、コールバックは非同期関数で、この場合はロックは非同期の実行が完全に完了するまで解放されません。
返値
ロックの解放後コールバックの結果で解決 (または拒否) し、要求が中断されると拒否される Promise を返します。
例外
このメソッドは、以下のいずれかの種類の DOMException で拒否される Promise を返す可能性があります。
InvalidStateErrorDOMException-
ドキュメントが完全にアクティブでない環境のとき。
SecurityErrorDOMException-
現在の環境でロックマネージャーが取得できないとき。
NotSupportedErrorDOMException-
nameがハイフン (-) で始まるとき、stealとifAvailableの両方がtrueに設定されているとき、signalが設定されておりかつstealとifAvailableの いずれか がtrueに設定されているとき。 AbortErrorDOMException-
signalが設定されており、中断されたとき。
例
>一般の例
以下の例では、非同期関数をコールバックとして用いる request() メソッドの基本的な使用法を示します。コールバックが呼び出されると、それが帰るまでこのオリジンで実行中の他のコードは my_resource を確保できません。
await navigator.locks.request("my_resource", async (lock) => {
// ロックを確保した
});
モードの例
以下の例では、リーダーとライターがどのように mode を用いるかを示します。
両方の関数が my_resource というロックを用いることに注意してください。do_read() は 'shared' モードでロックを要求します。これは、異なるイベントハンドラー・タブ・ワーカーが同時に呼び出せるということです。
async function do_read() {
await navigator.locks.request(
"my_resource",
{ mode: "shared" },
async (lock) => {
// ここで読み込みを行う
},
);
}
do_write() 関数は、同じロックを 'exclusive' モードで用います。これは、書き込み操作が完了するまで do_read() 関数内の request() の呼び出しを遅らせます。これはイベントハンドラー・タブ・ワーカーにまたがって適用されます。
async function do_write() {
await navigator.locks.request(
"my_resource",
{ mode: "exclusive" },
async (lock) => {
// ここで書き込みを行う
},
);
}
ifAvailable の例
既に確保されていないときのみロックを獲得するには、ifAvailable オプションを用います。この関数では、await によりメソッドをコールバックが完了するまで帰らないようにしています。ロックは利用可能なときのみ獲得できるので、この呼び出しはロックが他のどこかで解放されるのを待たずにすみます。
await navigator.locks.request(
"my_resource",
{ ifAvailable: true },
async (lock) => {
if (!lock) {
// ロックが獲得できなかったので、早期脱出する
return;
}
// ロックが獲得できた。このオリジンで実行中の他のコードは
// このコードが帰るまで 'my_res_lock' ロックを確保できない。
},
);
signal の例
短時間のみロックを待機するには、signal オプションを用います。
const controller = new AbortController();
// 200ms まで待つ
setTimeout(() => controller.abort(), 200);
try {
await navigator.locks.request(
"my_resource",
{ signal: controller.signal },
async (lock) => {
// ロックが獲得できた!
},
);
} catch (ex) {
if (ex.name === "AbortError") {
// ロックの獲得前に要求が中断された
}
}
仕様書
| 仕様書 |
|---|
| Web Locks API> # api-lock-manager-request> |