The Streams API provides a neat way of piping a ReadableStream
to a WritableStream
using readableStream.pipeTo(writableStream)
. This would appear to be more convenient than obtaining readableStream.getReader()
and manually gluing it to writableStream.getWriter()
or directly to underlying functionality.
I have a use case where I am provided a ReadableStream
object which may eventually need to "go away" and be replaced by a new ReadableStream
object. It would be nice to use a single custom WritableStream
to wrap the functionality which these ReadableStream
objects interface with and pipe them together for as long as needed, but have not found how to "undo" the piping process.
Q: Is it possible to "undo"/"break"/"teardown" a pipe created with .pipeTo()
, or are pipes "permanent" and not appropriate for this use case?
Example using Serial API, where I would like to be able to call doConnectPort()
and then doDisconnectPort()
repeatedly:
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();
}
Currently, I manually glue things together and clean up when it's time to disconnect the port:
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();
}
You can pass an AbortSignal in the
pipeTo
's option object'ssignal
.