Streams API: можно ли отменить .pipeTo()?
API Streams обеспечивает аккуратный способ трубопровода аReadableStream
к WritableStream
с помощью readableStream.pipeTo(writableStream)
. Это кажется более удобным, чем получениеreadableStream.getReader()
и вручную приклеив его к writableStream.getWriter()
или непосредственно к базовым функциям.
У меня есть вариант использования, когда мне предоставляется ReadableStream
объект, который в конечном итоге может потребоваться "уйти" и заменить новым ReadableStream
объект. Было бы неплохо использовать один кастомныйWritableStream
чтобы обернуть функциональность, которую эти ReadableStream
объекты взаимодействуют с ними и соединяют их вместе столько, сколько необходимо, но не нашли, как "отменить" этот процесс.
В: Можно ли "отменить" / "сломать" / "разорвать" канал, созданный с помощью .pipeTo()
, или трубы "постоянны" и не подходят для этого варианта использования?
Пример использования последовательного 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();
}
1 ответ
Вы можете передать сигнал 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>