javascript - Streams API:可以撤消 .pipeTo()?
问题描述
Streams API提供了一种将a管道ReadableStream
传输到WritableStream
using的简洁方法readableStream.pipeTo(writableStream)
。这似乎比获取readableStream.getReader()
并手动将其粘贴到writableStream.getWriter()
或直接粘贴到底层功能更方便。
我有一个用例,我提供了一个ReadableStream
最终可能需要“离开”并被新对象替换的ReadableStream
对象。最好使用单个自定义WritableStream
来包装这些ReadableStream
对象与之交互的功能,并根据需要将它们管道在一起,但还没有找到如何“撤消”管道过程。
问:是否可以“撤消”/“中断”/“拆除”使用创建的管道.pipeTo()
,或者管道是否“永久”且不适合此用例?
使用Serial API的示例,我希望能够在其中doConnectPort()
重复调用doDisconnectPort()
:
var customWritable = new WritableStream(…);
var port;
async function doConnectPort() {
port = await navigator.serial.requestPort();
await port.open({ baudrate: …});
await port.readable.pipeTo(customWritable);
}
async function doDisconnectPort() {
// What to do here? Can't close the port yet—port.readable is still locked!
await port.close();
}
目前,我手动将东西粘合在一起并在需要断开端口时进行清理:
var port;
var portReader;
async function doConnectPort() {
port = await navigator.serial.requestPort();
await port.open({ baudrate: …});
portReader = port.readable.getReader();
while (true) {
const { value, done } = await portReader.read();
if (done) {
break;
}
// do something with value
}
}
async function doDisconnectPort() {
await portReader.cancel();
await portReader.releaseLock();
await port.close();
}
解决方案
您可以在选项对象的中传递AbortSignal。pipeTo
signal
const btn = document.querySelector( "button" );
const checkbox = document.querySelector( "input" );
if( !ReadableStream.prototype.pipeTo ) {
console.warn( "Your browser doesn't support pipeTo" );
}
else {
btn.onclick = (evt) => {
console.clear( "" );
const blob = new Blob( [ "hello" ] );
const readable = blob.stream();
const target = new TransformStream();
const abort_controller = new AbortController();
target.readable.getReader().read().then( console.log );
readable.pipeTo( target.writable, { signal: abort_controller.signal } )
.catch( console.error )
if( checkbox.checked ) {
abort_controller.abort();
}
};
}
<label>Abort pipe<input type="checkbox" checked></label><br>
<button id="btn">new test</button>