recursal/MDN huggingface dataset:
OffscreenCanvas.transferToImageBitmap()
=======================================

Baseline 2023
-------------

Newly availableSince March 2023, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Learn more
* See full compatibility
* Report feedback
**实验性:** **这是一项实验性技术**  
在将其用于生产之前，请仔细检查浏览器兼容性表格。

**`OffscreenCanvas.transferToImageBitmap()`** 方法使用`offscreenCanvas`最近渲染得到的图片创建一个`ImageBitmap` 对象。

语法
--
```

ImageBitmap OffscreenCanvas.transferToImageBitmap()
```

### 返回值

一个`ImageBitmap`对象。

例子
--


```js
var offscreen = new OffscreenCanvas(256, 256);
var gl = offscreen.getContext("webgl");

//一些绘制要使用 gl 前后文

offscreen.transferToImageBitmap();
// ImageBitmap { width: 256, height: 256 }
```

Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-offscreencanvas-transfertoimagebitmap-dev |

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

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

浏览相关
----

* The interface defining this method, `OffscreenCanvas`
* `ImageBitmapRenderingContext.transferImageBitmap()` (en-US)
CSSStyleRule.selectorText
=========================

概述
--

**`CSSRule.selectorText`** 属性返回 CSS 规则的选择符文本，只读。动态设置 CSS 规则，请看 Using dynamic styling information (en-US).

语法
--
```

string = cssRule.selectorText
```

例子
--


```js
// for cssrule: body { background-color: darkblue; }
var stylesheet = document.styleSheets[0];

alert(stylesheet.cssRules[0].selectorText); // body
```

说明
--

浏览器解析选择符的时候可能会剔除不必要的空白字符

标准
--

* Document Object Model CSS - #CSS-CSSRuleCSS
style
=====

返回 一个 `CSSStyleDeclaration`接口对象，它代表了`CSSRule`的 declaration block。

语法
--
```

styleObj = cssRule.style
```

示例
--


```js
function stilo() {
  alert(document.styleSheets[0].cssRules[0].style.cssText);
}
// 弹出 "background-color: gray;"
```

备注
--

declaration block 是样式规则中花括号内的部分（选择器就在花括号的外部）

规范
--

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-cssstylerule-style |

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

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
MediaSession.setActionHandler()
===============================

**实验性:** **这是一项实验性技术**  
在将其用于生产之前，请仔细检查浏览器兼容性表格。

`MediaSession` 接口的属性 **`setActionHandler()`** 为 media session 动作设置一个监听器。这些动作让网页程序在用户操作设备的内置物理或屏上媒体控制项时收到消息，例如播放、停止或搜寻按钮。

语法
--
```

navigator.mediaSession.setActionHandler(type, callback)
```

### 参数

`type`

一个提供要监听的动作类型的 `DOMString` 。它可以是 `play`、`pause`、`seekbackward`、`seekforward`、`previoustrack` 或 `nexttrack`。

`callback`

一个在指定动作被调用时要调用的方法。回调方法不会收到参数，并且不应该返回值。

### 返回值

`undefined`。

使用说明
----

要移除一个已经存在的监听器，再调用一次 `setActionHandler()` ，将 `null` 作为回调方法。

示例
--

下面的示例创建一个新的 media session 并且为它添加监听器（不做任何事情）。


```js
if ("mediaSession" in navigator) {
  navigator.mediaSession.metadata = new MediaMetadata({
    title: "播客音乐名字",
    artist: "播客主持人",
    album: "播客名字",
    artwork: [{ src: "podcast.jpg" }],
  });
  navigator.mediaSession.setActionHandler("play", function () {});
  navigator.mediaSession.setActionHandler("pause", function () {});
  navigator.mediaSession.setActionHandler("seekbackward", function () {});
  navigator.mediaSession.setActionHandler("seekforward", function () {});
  navigator.mediaSession.setActionHandler("previoustrack", function () {});
  navigator.mediaSession.setActionHandler("nexttrack", function () {});
}
```


这个示例使用了适当的监听器来允许在不同的方向搜寻正在播放的媒体。


```js
let skipTime = 10; // 要跳过的秒数

navigator.mediaSession.setActionHandler("seekbackward", (evt) => {
  // 用户点击了“向后搜寻”的媒体按钮
  audio.currentTime = Math.max(audio.currentTime - skipTime, 0);
});

navigator.mediaSession.setActionHandler("seekforward", (evt) => {
  // 用户点击了“向前搜寻”的媒体按钮
  audio.currentTime = Math.min(audio.currentTime + skipTime, audio.duration);
});
```


要移除一个监听器，将它设为 null。


```js
navigator.mediaSession.setActionHandler("nexttrack", null);
```

规范
--

| Specification |
| --- |
| Media Session # dom-mediasession-setactionhandler |

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

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
IDBKeyRange.lowerBound()
========================

`IDBKeyRange` 接口的 **`lowerBound()`** 方法创建一个只有下限的新的键范围。默认情况下，它包含较低的端点值。

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

Syntax
------
```

var myIDBKeyRange = IDBKeyRange.lowerBound(lower);
var myIDBKeyRange = IDBKeyRange.lowerBound(lower, open);
```

### Parameters

lower

指定新键范围的下限。

open 可选

指示下限是否排除端点值。默认值为 false。

### Return value

`IDBKeyRange`: 新创建的键范围。

### Exceptions

此方法可能引发以下类型的 `DOMException` :

| Exception | Description |
| --- | --- |
| DataError | The value parameter passed was not a valid key. |

Example
-------

下面的示例演示如何使用下限键范围。在这里，我们声明`keyRangeValue = IDBKeyRange.lowerBound("F", false);`— 一个包含值“F”及其后所有内容的范围。我们打开一个事务（使用 `IDBTransaction`）和一个对象存储，并使用 `IDBObjectStore.openCursor`打开一个游标，声明`keyRangeValue` 为其可选的键范围值。这意味着光标将只检索键值为“F”及其后面的所有记录。如果使用`IDBKeyRange.lowerBound("F", true);`，则该范围将不包括端点“F”，仅包括其后面的值。

**备注：** 要获得一个更完整的示例，使你能够使用键范围进行实验，请查看我们的 IDBKeyRange-example（实时查看该示例）。


```js
function displayData() {
  var keyRangeValue = IDBKeyRange.lowerBound("F");

  var transaction = db.transaction(["fThings"], "readonly");
  var objectStore = transaction.objectStore("fThings");

  objectStore.openCursor(keyRangeValue).onsuccess = function (event) {
    var cursor = event.target.result;
    if (cursor) {
      var listItem = document.createElement("li");
      listItem.innerHTML =
        "<strong>" + cursor.value.fThing + "</strong>, " + cursor.value.fRating;
      list.appendChild(listItem);

      cursor.continue();
    } else {
      console.log("Entries all displayed.");
    }
  };
}
```

Specification
-------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbkeyrange-lowerbound① |

Browser compatibility
---------------------

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

See also
--------

* Using IndexedDB
* Starting transactions: `IDBDatabase`
* Using transactions: `IDBTransaction`
* Setting a range of keys: `IDBKeyRange`
* Retrieving and making changes to your data: `IDBObjectStore`
* Using cursors: `IDBCursor`
* Reference example: To-do Notifications (view example live.)
ReadableStream.cancel()
=======================

`ReadableStream` 接口的 **`cancel()`** 方法返回一个 `Promise`，这个 promise 会在流被取消的时候兑现。

cancel 用于在不再需要来自它的任何数据的情况下（即使仍有排队等待的数据块）完全结束一个流。调用 cancel 后该数据丢失，并且流不再可读。为了仍然可以读这些数据块而不完全结束这个流，你应该使用 `ReadableStreamDefaultController.close()`。

语法
--


```js
cancel()
cancel(reason)
```

### 参数

`reason` 可选

人类可读的取消原因。底层源代码可能会使用它。

### 返回值

一个 `Promise`，会在结束时使用给定的 `reason` 参数兑现。

### 异常

`TypeError`

它尝试取消的流不是 `ReadableStream`，或者它已被锁定。

示例
--

在 Jake Archibald 的取消一个 fetch 示例中，流用于逐块获取 WHATWG HTML 规范；并在每个块中搜索“service workers”字符串。当找到搜索词时，使用 `cancel()` 取消流——作业已被完成，因此不再需要它。


```js
var searchTerm = "service workers";
// Chars to show either side of the result in the match
var contextBefore = 30;
var contextAfter = 30;
var caseInsensitive = true;
var url = "https://html.spec.whatwg.org/";
console.log(`Searching '${url}' for '${searchTerm}'`);
fetch(url)
  .then((response) => {
    console.log("Received headers");
    var decoder = new TextDecoder();
    var reader = response.body.getReader();
    var toMatch = caseInsensitive ? searchTerm.toLowerCase() : searchTerm;
    var bufferSize = Math.max(toMatch.length - 1, contextBefore);
    var bytesReceived = 0;
    var buffer = "";
    var matchFoundAt = -1;
    return reader.read().then(function process(result) {
      if (result.done) {
        console.log("Failed to find match");
        return;
      }
      bytesReceived += result.value.length;
      console.log(`Received ${bytesReceived} bytes of data so far`);
      buffer += decoder.decode(result.value, { stream: true });
      // already found match & just context-gathering?
      if (matchFoundAt === -1) {
        matchFoundAt = (
          caseInsensitive ? buffer.toLowerCase() : buffer
        ).indexOf(toMatch);
      }
      if (matchFoundAt === -1) {
        buffer = buffer.slice(-bufferSize);
      } else if (
        buffer.slice(matchFoundAt + toMatch.length).length >= contextAfter
      ) {
        console.log("Here's the match:");
        console.log(
          buffer.slice(
            Math.max(0, matchFoundAt - contextBefore),
            matchFoundAt + toMatch.length + contextAfter,
          ),
        );
        console.log("Cancelling fetch");
        reader.cancel();
        return;
      } else {
        console.log("Found match, but need more context…");
      }
      // 保持读取
      return reader.read().then(process);
    });
  })
  .catch((err) => {
    console.log(
      "Something went wrong. See devtools for details. Does the response lack CORS headers?",
    );
    throw err;
  });
```

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-cancel③ |

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

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

参见
--

* `ReadableStream()` 构造函数
* 使用可读流
ReadableStream.pipeThrough()
============================

`ReadableStream` 接口的 **`pipeThrough()`** 方法提供了一种链式的方式，将当前流通过转换流或者其他任何一对可写/可读的流进行管道传输。

传输一个流通常在管道传输的时间内锁定这个流，以阻止其他 reader 锁定它。

语法
--


```js
pipeThrough(transformStream)
pipeThrough(transformStream, options)
```

### 参数

`transformStream`

由一对可读流和可写流组成的 `TransformStream`（或者结构为 `{writable, readable}` 的对象），它们共同工作以对数据进行转换。`writable` 流写入的数据在某些状态下可以被 `readable` 流读取。例如，向 `TextDecoder` 写入字节并从中读取字符串，而视频解码器则是写入编码的字节数据，并从中读取解压后的视频帧。

`options` 可选

传输至 `writable` 流应该被使用的选项。可用选项是：

`preventClose`

如果设置为 `true`，源 `ReadableStream` 的关闭将不再导致目标 `WritableStream` 关闭。一旦此过程完成，该方法返回的 promise 将被兑现；除非在关闭目标流时遇到错误，在这种情况下，它将因为该错误被拒绝。

`preventAbort`

如果设置为 `true`，源 `ReadableStream` 中的错误将不再中止目标 `WritableStream`。该方法返回的 promise 将因源流的错误或者任何在中止目地流期间的错误而被拒绝。

`preventCancel`

如果设置为 `true`，目标 `WritableStream` 的错误将不再取消源 `ReadableStream`。在这种情况下，该方法返回的 promise 将因源流的错误或者在取消源流期间发生的任何错误而被拒绝。此外，如果目标可写流开始关闭或者正在关闭，则源可读流将不再被取消。在这种情况下，方法返回的 promise 也将被拒绝，其错误为连接到一个已关闭的流或者在取消源流期间发生的任何错误。

`signal`

用于设置一个 `AbortSignal` 对象，然后可以通过相应的 `AbortController` 中止正在进行的传输操作。


### 返回值

`transformStream` 的 `readable` 端。

### 异常

`TypeError`

如果 `transformStream` 的 `writable` 和/或 `readable` 属性未定义，则抛出异常。

示例
--

在下面的例子中（有关运行实例的完整代码，参见解压 PNG，有关源代码，参见 png-transform-stream），使用 `fetch` 获取图像并将响应的 body 作为 `ReadableStream`。

接下来，我们记录可读流的内容，并且使用 `pipeThrough()` 将它发送到一个转换灰度图的转换流，然后记录新的流中的内容。


```js
// 通过 fetch 获取原始图像
fetch("png-logo.png")
  // 将响应的 body 作为 ReadableStream
  .then((response) => response.body)
  .then((rs) => logReadableStream("Fetch Response Stream", rs))
  // 从原始图像创造一个 PNG 的灰度图像
  .then((body) => body.pipeThrough(new PNGTransformStream()))
  .then((rs) => logReadableStream("PNG Chunk Stream", rs));
```

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-pipe-through② |

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

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

参见
--

* `ReadableStream()` 构造函数
* 链式管道传输
ReadableStream.ReadableStream()
===============================

**`ReadableStream()`** 构造函数创建并从给定的处理程序返回一个可读的流对象。

语法
--


```js
new ReadableStream()
new ReadableStream(underlyingSource)
new ReadableStream(underlyingSource, queuingStrategy)
```

### 参数

`underlyingSource` 可选

一个包含定义了构造流行为方法和属性的对象。`underlyingSource` 包括：

`start` (controller) 可选

 这是一个当对象被构造时立刻调用的方法。此方法的内容由开发人员定义，并应着眼于访问流，并执行其他任何必需的设置流功能。如果这个过程是异步完成的，它可以返回一个
 promise，表明成功或失败。传递给这个方法的 `controller` 是一个 `ReadableStreamDefaultController` 或 `ReadableByteStreamController` (en-US)，具体取决于 `type` 属性的值。开发人员可以使用此方法在设立期间控制流。


`pull` (controller) 可选

这个方法，也是由开发人员定义的，当流的内部队列不满时，会重复调用这个方法，直到队列补满。如果 `pull()` 返回一个 promise，那么它将不会再被调用，直到 promise 完成;如果 promise 失败，该流将会出现错误。传递给此方法的 `controller` 参数是 `ReadableStreamDefaultController` 或 `ReadableByteStreamController` (en-US)，具体取决于 `type` 属性的值。由于更多的块被获取，这个方法可以被开发人员用来控制流。

`cancel` (reason) 可选

 如果应用程序表示该流将被取消（例如，调用了 `ReadableStream.cancel()`，则将调用此方法，该方法也由开发人员定义。该方法应该做任何必要的事情来释放对流的访问。
 如果这个过程是异步的，它可以返回一个 promise，表明成功或失败。原因参数包含一个 `DOMString`，它描述了流被取消的原因。


`type` 可选

该属性控制正在处理的可读类型的流。如果它包含一个设置为 `bytes` 的值，则传递的控制器对象将是一个 `ReadableByteStreamController` (en-US)，能够处理 BYOB（带你自己的缓冲区）/字节流。如果未包含，则传递的控制器将为 `ReadableStreamDefaultController`。

`autoAllocateChunkSize` 可选

对于字节流，开发人员可以使用正整数值设置 `autoAllocateChunkSize` 以打开流的自动分配功能。启用此功能后，流实现将自动分配一个具有给定整数大小的 `ArrayBuffer`，并调用底层源代码，就好像消费者正在使用 BYOB reader 一样。


`queuingStrategy` 可选

一个可选择定义流的队列策略的对象。这需要两个参数：

`highWaterMark`

非负整数 - 这定义了在应用背压之前可以包含在内部队列中的块的总数。

`size(chunk)`

包含参数 `chunk` 的方法——这表示每个分块使用的大小（以字节为单位）。


**备注：** 你可以自定义 `queuingStrategy`，或者使用 `ByteLengthQueueingStrategy` (en-US) 或 `CountQueueingStrategy` (en-US) 的示例作为对象的值。如果 没有提供 `queuingStrategy`，则默认值与 highWaterMark 为 1 的 `CountQueuingStrategy` 相同。

### 返回值

`ReadableStream` 对象的实例。

### 异常

RangeError

提供的值既不是 `"bytes"` 也不是 `undefined`。

示例
--

在下面的简单示例中，使用构造函数创建了一个自定义的 `ReadableStream`（完整代码请参见我们的简单随机流示例）。`start()` 函数每秒生成一个随机的文本字符串并将它排入流中。如果因为任何原因调用 `ReadableStream.cancel()`，该 `cancel()` 函数也可以停止生成字符串。

按下按钮，将停止生成字符串，使用 `ReadableStreamDefaultController.close()` 关闭流，并且将运行另一个函数，从流中读取数据。


```js
const stream = new ReadableStream({
  start(controller) {
    interval = setInterval(() => {
      let string = randomChars();

      // Add the string to the stream
      controller.enqueue(string);

      // show it on the screen
      let listItem = document.createElement("li");
      listItem.textContent = string;
      list1.appendChild(listItem);
    }, 1000);

    button.addEventListener("click", function () {
      clearInterval(interval);
      fetchStream();
      controller.close();
    });
  },
  pull(controller) {
    // We don't really need a pull in this example
  },
  cancel() {
    // This is called if the reader cancels,
    // so we should stop generating strings
    clearInterval(interval);
  },
});
```

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-constructor⑤ |

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

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

参见
--

* `ReadableStream`
* `ReadableByteStreamController` (en-US)
* `ReadableStreamDefaultController`
* 使用可读流
ReadableStream.pipeTo()
=======================

`ReadableStream` 接口的 **`pipeTo()`** 方法通过管道将当前的 `ReadableStream` 中的数据传递给给定的 `WritableStream` 并且返回一个 `Promise`，promise 在传输成功完成时兑现，在遇到任何错误时则会被拒绝。

传输一个流时通常会在传输的持续时间内锁定这个流，以阻止其他 reader 锁定它。

语法
--


```js
pipeTo(destination)
pipeTo(destination, options)
```

### 参数

`destination`

充当 `ReadableStream` 最终目标的 `WritableStream`。

`options` 可选

传输至 `writable` 流应该被使用的选项。可用选项是：

`preventClose`

如果设置为 `true`，源 `ReadableStream` 的关闭将不再导致目标 `WritableStream` 关闭。一旦此过程完成，该方法将返回的 promise 将被兑现；除非在关闭目标时遇到错误，在这种情况下，它将因为该错误被拒绝。

`preventAbort`

如果设置为 `true`，源 `ReadableStream` 中的错误将不再中止目标 `WritableStream`。该方法返回的 promise 将因源流的错误或者任何在中止目地流期间的错误而被拒绝。

`preventCancel`

如果设置为 `true`，目标 `WritableStream` 的错误将不再取消源 `ReadableStream`。在这种情况下，该方法返回的 promise 将因源流的错误或者在取消源流期间发生的任何错误而被拒绝。此外，如果目标可写流开始关闭或者正在关闭，则源可读流将不再被取消。在这种情况下，方法返回的 promise 也将被拒绝，其错误为连接到一个已关闭的流或者在取消源流期间发生的任何错误。

`signal`

如果设置一个 `AbortSignal` 对象，然后可以通过相应的 `AbortController` 中止正在进行的传输操作。


### 返回值

返回一个 `Promise`，其在传输完成时兑现。

### 异常

`TypeError`

`writableStream` 且/或 `readableStream` 对象不是一个可写/可读流，或者其中一个或者两个流被锁定。

示例
--


```js
// 获取原始图像
fetch("png-logo.png")
  // 取回响应的 body 属性，该属性继承 ReadableStream
  .then((response) => response.body)
  .then((body) => body.pipeThrough(new PNGTransformStream()))
  .then((rs) => rs.pipeTo(new FinalDestinationStream()));
```

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-pipe-to④ |

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

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

参见
--

* `ReadableStream()` 构造函数
* 链式管道传输
ReadableStream：from() 静态方法
==========================

**实验性:** **这是一项实验性技术**  
在将其用于生产之前，请仔细检查浏览器兼容性表格。

**`ReadableStream.from()`** 静态方法从提供的可迭代或异步可迭代对象返回一个 `ReadableStream`。

该方法可以用于将可迭代或异步可迭代对象包装为可读流，包括数组、集合、promise 数组、异步生成器、`ReadableStream`、Node.js 可读流，等等。

语法
--


```js
ReadableStream.from(anyIterable)
```

### 参数

`anyIterable`

一个可迭代或异步可迭代对象。

### 返回值

一个 `ReadableStream`。

### 异常

`TypeError`

如果传入的参数不是可迭代对象或者异步可迭代对象（未定义 `@@iterator` 或 `@@asyncIterator` 方法），则抛出。如果在迭代期间，下一步的结果不是对象或者 promise 不能兑现对象，则也会抛出。

示例
--

### 将异步迭代器转换为可读流

这个在线示例演示了你如何将一个异步可迭代对象转换为 `ReadableStream`，然后如何消费这个流。

#### HTML

这个 HTML 由 `<pre>` 元素组成，用于日志记录。


```html
<pre id="log"></pre>
```


#### JavaScript

该示例代码创建了一个 `log()` 函数，用于将日志写入日志 HTML 元素。


```js
const logElement = document.getElementById("log");
function log(text) {
  logElement.innerText += `${text}\n`;
}
```


然后，检查是否支持静态方法，如果不支持，则记录不支持的结果。


```js
if (!ReadableStream.from) {
  log("不支持 ReadableStream.from()");
}
```


异步可迭代对象是一个匿名生成器函数，当它被调用三次时，它会产生值 1、2 和 3。该函数被传递给 `ReadableStream.from()`，以创建 `ReadableStream`。


```js
// 定义异步的迭代器
const asyncIterator = (async function\* () {
  yield 1;
  yield 2;
  yield 3;
})();

// 从迭代器创建 ReadableStream
const myReadableStream = ReadableStream.from(asyncIterator);
```


使用可读流示范了几种方式去消费流。以下使用 `for ...await` 循环的代码，因为这个方法是最简单的。循环的每次迭代都会记录来自流的当前分块。


```js
consumeStream(myReadableStream);

// 异步迭代 ReadableStream
async function consumeStream(readableStream) {
  for await (const chunk of myReadableStream) {
    // 使用每个分块做一些事情
    // 这里我们仅记录分块的值
    log(`chunk: ${chunk}`);
  }
}
```


#### 结果

消费流的输出如下所示（如果支持 `ReadableStream.from()`）。

### 将数组转换为 ReadableStream

该示例演示了如何将 `Array` 转换为 `ReadableStream`。
```

<pre id="log"></pre>
```


```
const logElement = document.getElementById("log");
function log(text) {
  logElement.innerText += `${text}\n`;
}

if (!ReadableStream.from) {
  log("不支持 ReadableStream.from()");
}
```


#### JavaScript

可迭代对象仅是一个字符串数组，它被传递给 `ReadableStream.from()` 以创建 `ReadableStream`。


```js
// 一个蔬菜名称的数组
const vegetables = ["Carrot", "Broccoli", "Tomato", "Spinach"];

// 从数组创建 ReadableStream
const myReadableStream = ReadableStream.from(vegetables);
```


```
consumeStream(myReadableStream);

// 异步迭代 ReadableStream
async function consumeStream(readableStream) {
  for await (const chunk of myReadableStream) {
    // 使用每个分块做一些事情
    // 这里我们仅记录分块的值
    log(`chunk: ${chunk}`);
  }
}
```


我们使用与之前示例相同的方式记录和消费流，因此这里不再展示。

#### 结果

输出如下所示。

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-from |

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

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

参见
--

* `ReadableStream`
* 使用可读流
ReadableStream.locked
=====================

`ReadableStream` 接口的只读属性 **`locked`** 返回可读流是否锁定到 reader。

一个可读流最多可以有一个激活的 reader，并且直到被释放之前都是锁定到该 reader。可以使用 `ReadableStream.getReader()` 方法获取 reader 然后使用 reader 的 `releaseLock()` 方法释放可读流。

值
-

一个布尔值，表示可读流是否已锁定。

示例
--


```js
const stream = new ReadableStream({
  ...
});
const reader = stream.getReader();
stream.locked
// 应返回 true，表示流已经锁定到了一个 reader
```

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-locked② |

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

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

参见
--

* `ReadableStream()` 构造函数
* 使用可读流
ReadableStream.getReader()
==========================

`ReadableStream` 接口的 **`getReader()`** 方法会创建一个 `reader`，并将流锁定。只有当前 `reader` 将流释放后，其他 `reader` 才能使用。

语法
--


```js
getReader()
getReader(mode)
```

### 参数

`mode` 可选

具有 `mode` 参数的对象，值为 `DOMString` 类型，用来指定要创建的 reader 的类型。其值可以是：

* `"byob"`，结果为 `ReadableStreamBYOBReader` (en-US) 类型，可读取可读字节流。
* `undefined`（或不指定——缺省值），返回 `ReadableStreamDefaultReader`，可以从流中返回单个分块。

### 返回值

`ReadableStreamDefaultReader` 类型或 `ReadableStreamBYOBReader` (en-US) 类型的实例，取决于 `mode` 值。

### 异常

`RangeError`

提供的 mode 值既不是 `"byob"` 也不是 `undefined`。

`TypeError`

尝试创建 reader 的流不是 `ReadableStream` 类型。

示例
--

下面是个简单的例子，在读取 `ReadableStream` 前，使用 `getReader()` 创建一个 `ReadableStreamDefaultReader`。（查看全部代码：Simple random stream example）。按顺序读取每个分块，并传递给 UI，当整个流被读取完毕后，从递归方法中退出，并在 UI 的另一部分输出整个流。


```js
function fetchStream() {
  const reader = stream.getReader();
  let charsReceived = 0;

  // read() 返回了一个 promise
  // 当数据被接收时 resolve
  reader.read().then(function processText({ done, value }) {
    // Result 对象包含了两个属性：
    // done - 当 stream 传完所有数据时则变成 true
    // value - 数据片段。当 done 为 true 时始终为 undefined
    if (done) {
      console.log("Stream complete");
      para.textContent = value;
      return;
    }

    // value for fetch streams is a Uint8Array
    charsReceived += value.length;
    const chunk = value;
    let listItem = document.createElement("li");
    listItem.textContent =
      "Received " +
      charsReceived +
      " characters so far. Current chunk = " +
      chunk;
    list2.appendChild(listItem);

    result += chunk;

    // 再次调用这个函数以读取更多数据
    return reader.read().then(processText);
  });
}
```

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-get-reader⑤ |

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

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

参见
--

* `ReadableStream()` 构造函数
* `ReadableStreamDefaultReader`
* `ReadableStreamBYOBReader` (en-US)
* 使用可读流
* 使用可读字节流 (en-US)
ReadableStream.tee()
====================

`ReadableStream` 接口的 **`tee()`** 方法对当前的可读流进行拷贝（tee），返回包含两个 `ReadableStream` 实例分支的数组。

这对于两个 reader 顺序的读取或者同时读取流有很大用处（可能以不同的速度）。例如，如果你想要从服务器获取一个响应，然后流式的传输到浏览器，并且也将它流式的传输到 ServiceWorker 缓存中，你可以在 ServiceWorker 执行此操作。由于响应体不能多次使用，你需要两个副本才能这么做。

一个被拷贝的（teed）流将发出两个 `ReadableStream` 分支中其中较*快*速率的消费者控制背压，并且内部队列中未读的数据在 `ReadableStream` 上被较慢的消费，没有任何限制或者背压。因此，当两个内部分支*都*有一个未读的元素时，原来的 `ReadableStream` 的控制器的内部队列将开始填充满，并且当它的 `desiredSize` ≤ 0 或字节流控制器 `desiredSize` (en-US) ≤ 0，然后控制器将停止在底层源上调用 `pull(controller)`，并且传递给 `new ReadableStream()`。如果仅有一个分支被消费，那么主体将会在内存中排队。因此，你不应该使用内置的 `tee()` 去以不同的速度并行读取非常大的流。相反，搜寻一个完全背压到以较*慢*速度消耗分支的实现。

要取消流，需要去取消两个生成的分支。正在被拷贝的流通常会在持续时间内被锁定，阻止其他的 reader 锁定它。

语法
--


```js
tee()
```

### 参数

无。

### 返回值

一个包含两个 `ReadableStream` 实例的 `Array`。

### 异常

`TypeError`

如果源流不是一个 `ReadableStream` 则抛出。

示例
--

在下面的简单示例中，一个先前生成的流被拷贝（tee），然后将两个生成的流（包含在生成的数组的两个成员中）传递给一个函数，该函数将从两个流中读取数据并且将每个流的分块按顺序打印到不同的 UI 部分。完整代码参见简单 tee 示例。


```js
function teeStream() {
  const teedOff = stream.tee();
  fetchStream(teedOff[0], list2);
  fetchStream(teedOff[1], list3);
}

function fetchStream(stream, list) {
  const reader = stream.getReader();
  let charsReceived = 0;

  // read() returns a promise that resolves
  // when a value has been received
  reader.read().then(function processText({ done, value }) {
    // Result objects contain two properties:
    // done - true if the stream has already given you all its data.
    // value - some data. Always undefined when done is true.
    if (done) {
      console.log("Stream complete");
      return;
    }

    // value for fetch streams is a Uint8Array
    charsReceived += value.length;
    const chunk = value;
    let listItem = document.createElement("li");
    listItem.textContent =
      "Read " + charsReceived + " characters so far. Current chunk = " + chunk;
    list.appendChild(listItem);

    // Read some more, and call this function again
    return reader.read().then(processText);
  });
}
```

规范
--

| Specification |
| --- |
| Streams Standard # ref-for-rs-tee② |

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

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

参见
--

* `ReadableStream()` 构造函数
* 拷贝流
CSSValueList.length
===================

**已弃用:** 不再推荐使用该特性。虽然一些浏览器仍然支持它，但也许已从相关的 web 标准中移除，也许正准备移除或出于兼容性而保留。请尽量不要使用该特性，并更新现有的代码；参见本页面底部的兼容性表格以指导你作出决定。请注意，该特性随时可能无法正常工作。

`CSSValueList` 接口的只读属性 **`length`** 表示列表中的 `CSSValue` 数量。有效的索引区间为 `0` 到 `length-1`。

语法
--
```

var length = cssValueList.length;
```

### 值

一个 `unsigned long` 数值，表示此列表中 `CSSValue` 的个数。

规范
--

该特性最初在 DOM Style Level 2 中定义，但从那时起已从标准化工作中移除。

它已被现代、不兼容的 CSS 类型对象模型 API (en-US) 取代，该 API 已被标准化。

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

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