LockManager：request() 方法
========================

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

`LockManager` 接口的 **`request()`** 方法请求一个 `Lock` 对象，该方法发参数指定返回对象的名称和特征。请求的 `Lock` 对象被传递给回调，而函数本身返回一个 `Promise`，在锁被释放后解析（或拒绝）回调的结果，或者在请求被中止时拒绝。

`options` 参数的 `mode` 属性可以接收 `"exclusive"` 或 `"shared"`。

当锁一次只能由一个代码实例持有时，请求 `"exclusive"` 锁。这适用于标签页和 worker 中的代码。使用它来表示对资源的互斥访问。当持有给定名称的 `"exclusive"` 锁时，不能持有其他同名的锁。

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

这种共享/独占锁模式在数据库事务架构中很常见，例如允许多个并发读取器（每个读取器请求一个 `"shared"` 锁），但仅允许一个写入器（单个 `"exclusive"` 锁）。这称为读者——作者模式。在 IndexedDB API 中，这被暴露为具有相同语义的 `"readonly"` 和 `"readwrite"` 事务。

**备注：** 此特性在 Web Worker 中可用

语法
--


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

### 参数

`name`

你想要请求的锁的标识符。

`options` 可选

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

`mode` 可选

`"exclusive"` 或 `"shared"` 之一。默认值是· `"exclusive"`。

`ifAvailable` 可选

如果为 `true`，则只有在尚未持有锁定请求时才会授予该锁定请求。如果无法授予，则将传入 `null` 而非 `Lock` 实例来调用回调。默认值为 `false`。

`steal` 可选

如果为 `true`，则任何持有的同名锁将被释放，并且请求将被授予，抢占任何排队中的锁请求。默认值为 `false`。

**警告：** 小心使用！之前在锁内运行的代码会继续运行，并且可能与现在持有锁的代码发生冲突。

`signal` 可选

一个 `AbortSignal`（`AbortController` 的 `signal` 属性）；如果指定并且 `AbortController` 被中止，则锁请求将被丢弃（如果尚未授予）。


`callback`

授予锁时调用的方法。当回调返回（或抛出异常）时，锁会自动释放。通常回调是一个异步函数，这会导致只有当异步函数完全完成时才会释放锁。

### 返回值

一个 `Promise`，在锁释放后解析（或拒绝）回调结果，或者拒绝若请求中止。

### 异常

此方法可能会返回一个被以下类型之一的 `DOMException` 拒绝的 promise：

`InvalidStateError` `DOMException`

如果当前环境的文档未完全激活，则抛出该异常。

`SecurityError` `DOMException`

如果无法获取当前环境的锁管理器，则抛出该异常。

`NotSupportedError` `DOMException`

如果 `name` 以连字符（`-`）开头，或选项 `steal` 和 `ifAvailable` 均为 `true`，或者选项 `signal` 存在且选项 `steal` 或 `ifAvailable` 为 `true`。

`AbortError` `DOMException`

如果选项 `signal` 存在并且被中止，则抛出该异常。

示例
--

### 一般示例

以下示例显示了 `request()` 方法的基本用法，并以异步函数作为回调函数。一旦调用回调函数，该源上的其他正在运行的代码就无法持有 `my_resource` 锁，直到回调返回。


```js
await navigator.locks.request("my\_resource", async (lock) => {
  // 锁被授予。
});
```

### `mode` 示例

以下示例展示了如何为读取器和写入器使用 `mode` 选项。

请注意，这两个函数都使用名为 `my_resource` 的锁。`do_read()` 请求 `'shared'` 模式下的锁定，这意味着多个调用可能会在不同的事件处理器、标签页或 worker 中同时发生。


```js
async function do\_read() {
  await navigator.locks.request(
    "my\_resource",
    { mode: "shared" },
    async (lock) => {
      // 在这里放置执行读取器具体操作的代码。
    },
  );
}
```


`do_write()` 函数使用相同的锁，但处于 `'exclusive'` 模式，这将延迟 `do_read()` 中 `request()` 的调用，直到写操作完成。这适用于事件处理器、标签页或 worker。


```js
async function do\_write() {
  await navigator.locks.request(
    "my\_resource",
    { mode: "exclusive" },
    async (lock) => {
      // 在这里放置执行写入器具体操作的代码。
    },
  );
}
```

### `ifAvailable` 示例

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


```js
await navigator.locks.request(
  "my\_resource",
  { ifAvailable: true },
  async (lock) => {
    if (!lock) {
      // 锁没有被授予——尽快结束。
      return;
    }

    // 该锁已被授予，并且该源中没有其他正在运行的代码持有 'my\_res\_lock' 锁，直到该锁返回为止。
  },
);
```

### `signal` 示例

如果只等待锁一小段时间，请使用 `signal` 选项。


```js
const controller = new AbortController();
// 最多等待 200 毫秒。
setTimeout(() => controller.abort(), 200);

try {
  await navigator.locks.request(
    "my\_resource",
    { signal: controller.signal },
    async (lock) => {
      // 锁被获取了！
    },
  );
} catch (ex) {
  if (ex.name === "AbortError") {
    // 该请求在获得锁之前就中止了。
  }
}
```

规范
--

| Specification |
| --- |
| Web Locks API # api-lock-manager-request |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.