首页 > 解决方案 > Streams API:可以撤消 .pipeTo()?

问题描述

Streams API提供了一种将a管道ReadableStream传输到WritableStreamusing的简洁方法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();
}

标签: javascriptserial-portwhatwg-streams-api

解决方案


您可以在选项对象的中传递AbortSignalpipeTosignal

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>


推荐阅读