WritableStream()
================

**`WritableStream()`** 构造函数创建一个新的 `WritableStream` 对象实例。

语法
--


```js
new WritableStream(underlyingSink)
new WritableStream(underlyingSink, queuingStrategy)
```

### 参数

`underlyingSink` 可选

一个包含方法和属性的对象，这些方法和属性定义了构造的流的实例的具体行为。`underlyingSource` 可以包括：

`start(controller)` 可选

这是一个当对象被构造时立刻调用的方法。此方法的内容由开发人员定义，并应着眼于访问流，并执行其他任何必需的设置流功能。如果这个过程是异步完成的，它可以返回一个 promise，以表明异步操作成功或失败。传递给这个方法的 `controller` 参数是一个 `WritableStreamDefaultController`。开发人员可以在设置时使用它来控制流。

`write(chunk, controller)` 可选

当一个新的数据块（指定为 `chunk` 参数传入）准备好写入底层接收器时，将调用此方法，该方法也由开发人员定义。它可以返回一个 promise 来表示写入操作的成功或者失败。传递给这个方法的 `controller` 参数是一个 `WritableStreamDefaultController`，当提交了更多的块进行写入时，开发人员可以使用它来控制流。这个方法仅在上一次写入成功后才会被再次调用，并且永远不会在流关闭或者中止后被调用（见下文）。

`close(controller)` 可选

如果应用程序发出已经完成了所有分块的写入的信号，将调用此方法，该方法也是由开发人员定义。其应该完成向底层接收器的数据写入，然后释放对它的访问。如果这个过程是异步完成的，它可以返回一个 promise，以表明操作成功或失败。这个方法只有在所有等待的写入操作都成功后才会被调用。传递给这个方法的 `controller` 参数是一个 `WritableStreamDefaultController`，可用于写入结束时控制流。

`abort(reason)` 可选

如果应用程序发出希望立即关闭流并且将其移至错误状态的信号，将调用此方法，该方法也是由开发人员定义。它可以清理任何被占用的资源，就像 `close()` 一样，但是即使存在等待的写入操作，`abort()` 也将被调用——那些分块将被丢弃。如果这个过程是异步完成的，它可以返回一个 promise，以表明操作成功或失败。`reason` 参数包含一个字符串，用于指定流被中止的原因。


`queuingStrategy` 可选

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

`highWaterMark`

非负整数——这定义了在应用背压之前可以包含在内部队列中的分块的最大数量。

`size(chunk)`

包含参数 chunk 的方法——这表示每个分块所需要使用的字节数。


**备注：** 你可以定义一个自己的 `queuingStrategy`，或者为这个对象值使用 `ByteLengthQueuingStrategy` 或 `CountQueuingStrategy` 的实例。如果没有提供 `queuingStrategy`，则使用的默认值与 `CountQueuingStrategy` 相同，其 highWaterMark 为 1。

### 返回值

`WritableStream` 对象的一个实例。

示例
--

下面的例子说明了这个接口的几个功能。它展示了使用自定义接收器和由 API 提供的队列策略创建的 `WritableStream`。然后它调用一个 `sendMessage()` 的函数，传递新创建的流和一个字符串。在这个函数内部，它调用流的 `getWriter()` 方法，该方法返回一个 `WritableStreamDefaultWriter` 实例。`forEach()` 用于将字符串的每个分块写入流。最后，`write()` 和 `close()` 方法都会返回 promise，promise 的状态由对应的操作是否成功来决定。


```js
const list = document.querySelector("ul");

function sendMessage(message, writableStream) {
  // defaultWriter is of type WritableStreamDefaultWriter
  const defaultWriter = writableStream.getWriter();
  const encoder = new TextEncoder();
  const encoded = encoder.encode(message, { stream: true });
  encoded.forEach((chunk) => {
    defaultWriter.ready
      .then(() => {
        return defaultWriter.write(chunk);
      })
      .then(() => {
        console.log("Chunk written to sink.");
      })
      .catch((err) => {
        console.log("Chunk error:", err);
      });
  });
  // Call ready again to ensure that all chunks are written
  // before closing the writer.
  defaultWriter.ready
    .then(() => {
      defaultWriter.close();
    })
    .then(() => {
      console.log("All chunks written");
    })
    .catch((err) => {
      console.log("Stream error:", err);
    });
}

const decoder = new TextDecoder("utf-8");
const queuingStrategy = new CountQueuingStrategy({ highWaterMark: 1 });
let result = "";
const writableStream = new WritableStream(
  {
    // Implement the sink
    write(chunk) {
      return new Promise((resolve, reject) => {
        var buffer = new ArrayBuffer(1);
        var view = new Uint8Array(buffer);
        view[0] = chunk;
        var decoded = decoder.decode(view, { stream: true });
        var listItem = document.createElement("li");
        listItem.textContent = "Chunk decoded: " + decoded;
        list.appendChild(listItem);
        result += decoded;
        resolve();
      });
    },
    close() {
      var listItem = document.createElement("li");
      listItem.textContent = "[MESSAGE RECEIVED] " + result;
      list.appendChild(listItem);
    },
    abort(err) {
      console.log("Sink error:", err);
    },
  },
  queuingStrategy,
);
sendMessage("Hello, world.", writableStream);
```


你可以在我们的简单的 writer 示例找到完整代码。

### 背压

由于 API 支持背压的方式（其在代码中的实现）可能不太明显。要了解背压是如何实现的，请注意以下三点：

* 为创建计数策略（第 35 行）而设置的 `highWaterMark` 属性，其用于设置 `WritableStream` 实例处理单个 `write()` 操作时可接受的最大数据量。在该示例中，它是可以传递给 `defaultWriter.write()` 的最大数据量（第 11 行）。
* `defaultWriter.ready` 属性返回一个当 sink（`WritableStream` 构造函数的第一个属性）完成写入数据时兑现的 promise。数据源可以写入更多的数据（第 9 行）或者调用 `close()`（第 24 行）。过早调用 close() 会阻止数据写入。这就是示例调用 `defaultWriter.ready` 两次的原因（第 9 行和第 22 行）。
* 接收器的 `write()` 方法（第 40 行）返回的 `Promise` 告诉 `WritableStream` 和它的 writer 何时去兑现 `defaultWriter.ready`。
规范
--

| Specification |
| --- |
| Streams Standard # ref-for-ws-constructor④ |

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

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