首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何关闭已通过TransformStream传输的网络串行端口?

如何关闭已通过TransformStream传输的网络串行端口?
EN

Stack Overflow用户
提问于 2022-02-25 07:28:04
回答 1查看 1.3K关注 0票数 2

我有一个Web串行端口,我想从中读取一些数据。我想使用TransformStream进行一些处理(例如,将字节解码为字符串、分离逻辑消息等),方法是使用pipeThrough来转换数据。但是,一旦我这样做了,就不能再通过调用reader.releaseLock()来释放端口上的锁了。我在这里做错什么了?

这段代码按照我预期的方式运行(在安全上下文中不依赖于浏览器):

代码语言:javascript
运行
复制
async serialTestWorking() {
  const port = await navigator.serial.requestPort();

  await port.open({baudRate: 9600});
  console.log("Is locked after open?", port.readable.locked);
  // Prints "Is locked after open? false"

  let reader = port.readable.getReader();
  console.log("Is locked after getReader?", port.readable.locked);
  // Prints "Is locked after getReader? true"

  reader.releaseLock();
  console.log("Is locked after releaseLock?", port.readable.locked);
  // Prints "Is locked after releaseLock? false"

  await port.close();
  console.log("Port closed");
  // Prints "Port closed"
}

但是,如果我使用pipeThrough将输出发送到一个“无所事事”的TransformStream中,它就会分崩离析。锁不会在releaseLock中释放,最终的close也无法工作。

代码语言:javascript
运行
复制
async serialTestBroken() {
  const port = await navigator.serial.requestPort();

  await port.open({baudRate: 9600});
  console.log("Is locked after open?", port.readable.locked);
  // Prints "Is locked after open? false"

  let reader = port.readable.pipeThrough(new TransformStream()).getReader();
  console.log("Is locked after getReader?", port.readable.locked);
  // Prints "Is locked after getReader? true"

  reader.releaseLock();
  console.log("Is locked after releaseLock?", port.readable.locked);
  // Prints "Is locked after releaseLock? true"

  await port.close();
  console.log("Port closed");
  // Doesn't make it to the log line
  //throws "TypeError: Failed to execute 'close' on 'SerialPort': Cannot cancel a locked stream"
}

我在这里做错什么了?释放TransformStream上的锁真的不会在上游传播吗?我是否必须跟踪每一个变压器在我的管道中的实例,这样我就可以确保全部解锁?

流规范说管道在管道操作期间锁定可读的和可写的流。

管道锁定可读和可写流,防止在管道操作期间对它们进行操作。这允许实现执行重要的优化,例如直接将数据从基础源传送到基础接收器,同时绕过许多中间队列。

我是否有其他方法表示“管道操作”已经完成?

EN

Stack Overflow用户

回答已采纳

发布于 2022-02-25 08:35:32

正如https://web.dev/serial/#close-port中所解释的,如果其readablewritable成员未锁定,则port.close()将关闭串行端口,这意味着已经为它们各自的读取器和写入器调用了releaseLock()

但是,当使用转换流时,关闭串行端口要复杂一些。打电话给reader.cancel(),然后打给writer.close()port.close()。这会将错误通过转换流传播到基础串行端口。因为错误传播不会立即发生,所以需要使用先前创建的readableStreamClosedwritableStreamClosed承诺来检测port.readableport.writable何时被解锁。取消读取器会导致流中止;这就是您必须捕获并忽略结果错误的原因。

代码语言:javascript
运行
复制
const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable.getReader();

// Listen to data coming from the serial device.
while (true) {
  const { value, done } = await reader.read();
  if (done) {
    reader.releaseLock();
    break;
  }
  // value is a string.
  console.log(value);
}
代码语言:javascript
运行
复制
// Later...

const textEncoder = new TextEncoderStream();
const writer = textEncoder.writable.getWriter();
const writableStreamClosed = textEncoder.readable.pipeTo(port.writable);

reader.cancel();
await readableStreamClosed.catch(() => { /* Ignore the error */ });

writer.close();
await writableStreamClosed;

await port.close();
票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71262432

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档