WritableStream

基线 2022

新可用

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

注意:此功能在Web Workers中可用。

Streams APIWritableStream接口为将流式数据写入目标(称为接收器)提供了一种标准抽象。此对象具有内置的反压和排队功能。

WritableStream 是一个可传输对象

构造函数

WritableStream()

创建一个新的WritableStream对象。

实例属性

WritableStream.locked 只读

一个布尔值,指示WritableStream是否锁定到写入器。

实例方法

WritableStream.abort()

中止流,表示生产者无法再成功写入流,并且它将立即进入错误状态,并丢弃任何排队的写入操作。

WritableStream.close()

关闭流。

WritableStream.getWriter()

返回一个新的WritableStreamDefaultWriter实例,并将流锁定到该实例。在流被锁定期间,在释放此写入器之前,无法获取其他写入器。

示例

以下示例说明了此接口的几个特性。它展示了使用自定义接收器和 API 提供的排队策略创建WritableStream的过程。然后,它调用一个名为sendMessage()的函数,并将新创建的流和一个字符串作为参数传递。在该函数内部,它调用流的getWriter()方法,该方法返回一个WritableStreamDefaultWriter实例。使用forEach()调用将字符串的每个块写入流。最后,write()close()返回一些承诺,这些承诺被处理以处理块和流的成功或失败。

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);
  encoded.forEach((chunk) => {
    defaultWriter.ready
      .then(() => 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) => {
        const buffer = new ArrayBuffer(1);
        const view = new Uint8Array(buffer);
        view[0] = chunk;
        const decoded = decoder.decode(view, { stream: true });
        const listItem = document.createElement("li");
        listItem.textContent = `Chunk decoded: ${decoded}`;
        list.appendChild(listItem);
        result += decoded;
        resolve();
      });
    },
    close() {
      const listItem = document.createElement("li");
      listItem.textContent = `[MESSAGE RECEIVED] ${result}`;
      list.appendChild(listItem);
    },
    abort(err) {
      console.log("Sink error:", err);
    },
  },
  queuingStrategy,
);

sendMessage("Hello, world.", writableStream);

您可以在我们的简单写入器示例中找到完整代码。

背压

由于 API 中支持背压的方式,因此其在代码中的实现可能不那么明显。要了解背压是如何实现的,请查找三件事

  • highWaterMark属性,在使用new CountQueuingStrategy创建计数策略时设置,它设置了WritableStream实例在单个write()操作中处理的最大数据量。在此示例中,它是可以发送到defaultWriter.write()(在sendMessage函数中)的最大数据量。
  • defaultWriter.ready属性返回一个承诺,当接收器(WritableStream构造函数的第一个属性)完成数据写入时,该承诺将被解决。数据源可以使用defaultWriter.write()写入更多数据,或者调用defaultWriter.close(),如上例所示。过早调用close()可能会阻止数据写入。这就是为什么示例会调用两次defaultWriter.ready的原因。
  • 接收器的write()方法返回的Promise告诉WritableStream及其写入器何时解决defaultWriter.ready

规范

规范
流标准
# ws-class

浏览器兼容性

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

另请参阅