Streams API: можно ли отменить .pipeTo ()? - PullRequest
0 голосов
/ 09 июля 2020

API Streams обеспечивает удобный способ соединения ReadableStream с WritableStream с помощью readableStream.pipeTo(writableStream). Это кажется более удобным, чем получение readableStream.getReader() и ручное приклеивание его к writableStream.getWriter() или непосредственно к базовым функциям.

У меня есть вариант использования, когда мне предоставляется объект ReadableStream, который в конечном итоге может потребоваться на «go прочь» и заменить его новым объектом ReadableStream. Было бы неплохо использовать один настраиваемый WritableStream, чтобы обернуть функциональность, с которой взаимодействуют эти ReadableStream объекты, и связать их вместе столько, сколько необходимо, но не нашли, как «отменить» процесс конвейера.

Q: Можно ли «отменить» / «разорвать» / «разорвать» канал, созданный с помощью .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();
}

1 Ответ

1 голос
/ 20 июля 2020

Вы можете передать AbortSignal в signal объекта опций pipeTo.

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...