WritableStream()
WritableStream()
构造函数创建一个新的 WritableStream
对象实例。
语法
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 的状态由对应的操作是否成功来决定。
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