LockManager: request() 方法

基线 2022

新可用

2022 年 3 月起,此功能在最新的设备和浏览器版本中均可使用。此功能可能在旧设备或浏览器中无法使用。

安全上下文:此功能仅在 安全上下文 (HTTPS) 中可用,在部分或所有 支持的浏览器 中可用。

注意:此功能在 Web 工作线程 中可用。

request() 方法是 LockManager 接口的方法,用于请求一个 Lock 对象,其参数指定了锁的名称和特征。请求的 Lock 会传递给回调函数,而该函数本身会返回一个 Promise,该 Promise 在锁释放后会使用回调函数的结果来解析(或拒绝),如果请求被中止,则会拒绝。

options 参数的 mode 属性可以是 "exclusive""shared"

当应仅由一个代码实例同时持有锁时,请求 "exclusive" 锁。这适用于标签和工作线程中的代码。使用此方法来表示对资源的互斥访问。当持有给定名称的 "exclusive" 锁时,不能再持有或授予具有相同名称的其他锁。

当代码的多个实例可以共享对资源的访问时,请求 "shared" 锁。当持有给定名称的 "shared" 锁时,可以授予具有相同名称的其他 "shared" 锁,但不能持有或授予具有该名称的 "exclusive" 锁。

这种共享/排他锁模式在数据库事务体系结构中很常见,例如,允许多个并发读取器(每个读取器请求 "shared" 锁),但只允许一个写入器(一个 "exclusive" 锁)。这被称为读写器模式。在 IndexedDB API 中,这表现为 "readonly""readwrite" 事务,它们具有相同的语义。

语法

js
request(name, callback)
request(name, options, callback)

参数

name

要请求的锁的标识符。

options 可选

描述要创建的锁的特征的对象。有效值为

mode 可选

"exclusive""shared"。默认值为 "exclusive"

ifAvailable 可选

如果为 true,则只有在锁未被持有时才授予锁请求。如果无法授予,则回调函数将被调用,并返回 null 而不是 Lock 实例。默认值为 false

steal 可选

如果为 true,则会释放任何具有相同名称的持有锁,并授予请求,优先于任何排队的请求。默认值为 false

警告:谨慎使用!以前在锁内运行的代码将继续运行,并且可能与现在持有锁的代码发生冲突。

signal 可选

一个 AbortSignalsignal 属性为 AbortController);如果指定并 AbortController 被中止,则锁请求将被丢弃,前提是它尚未被授予。

callback

当授予锁时调用的方法。当回调函数返回(或抛出异常)时,锁会自动释放。通常,回调函数是一个异步函数,这会导致锁仅在异步函数完全完成时才释放。

返回值

一个 Promise,在锁释放后使用回调函数的结果来解析(或拒绝),如果请求被中止,则会拒绝。

异常

此方法可能会返回一个被拒绝的 Promise,其中包含以下类型之一的 DOMException

InvalidStateError DOMException

如果环境文档未完全激活,则抛出此异常。

SecurityError DOMException

如果无法为当前环境获取锁管理器,则抛出此异常。

NotSupportedError DOMException

如果 name 以连字符 (-) 开头,选项 stealifAvailable 都为 true,或者选项 signal 存在,且选项 stealifAvailabletrue,则抛出此异常。

AbortError DOMException

如果选项 signal 存在且被中止,则抛出此异常。

示例

一般示例

以下示例展示了使用 request() 方法的基本用法,其中回调函数是一个异步函数。一旦调用回调函数,在此源上的其他任何运行代码都不能持有 my_resource,直到回调函数返回。

js
await navigator.locks.request("my_resource", async (lock) => {
  // The lock was granted.
});

mode 示例

以下示例展示了如何使用 mode 选项来进行读写操作。

请注意,这两个函数都使用名为 my_resource 的锁。do_read() 请求 'shared' 模式的锁,这意味着多个调用可以在不同的事件处理程序、标签或工作线程中同时发生。

js
async function do_read() {
  await navigator.locks.request(
    "my_resource",
    { mode: "shared" },
    async (lock) => {
      // Read code here.
    },
  );
}

do_write() 函数使用相同的锁,但使用 'exclusive' 模式,这将延迟 do_read() 中的 request() 调用的调用,直到写入操作完成。这适用于事件处理程序、标签或工作线程。

js
async function do_write() {
  await navigator.locks.request(
    "my_resource",
    { mode: "exclusive" },
    async (lock) => {
      // Write code here.
    },
  );
}

ifAvailable 示例

要仅在锁未被持有时才获取锁,请使用 ifAvailable 选项。在这个函数中,await 表示该方法不会返回,直到回调函数完成。由于锁仅在可用时才授予,因此此调用避免了需要等待锁在其他地方释放。

js
await navigator.locks.request(
  "my_resource",
  { ifAvailable: true },
  async (lock) => {
    if (!lock) {
      // The lock was not granted - get out fast.
      return;
    }

    // The lock was granted, and no other running code in this origin is holding
    // the 'my_res_lock' lock until this returns.
  },
);

signal 示例

要仅等待短时间获取锁,请使用 signal 选项。

js
const controller = new AbortController();
// Wait at most 200ms.
setTimeout(() => controller.abort(), 200);

try {
  await navigator.locks.request(
    "my_resource",
    { signal: controller.signal },
    async (lock) => {
      // The lock was acquired!
    },
  );
} catch (ex) {
  if (ex.name === "AbortError") {
    // The request aborted before it could be granted.
  }
}

规范

规范
Web 锁 API
# api-lock-manager-request

浏览器兼容性

BCD 表格仅在启用了 JavaScript 的浏览器中加载。