我有一个Web串行端口,我想从中读取一些数据。我想使用TransformStream
进行一些处理(例如,将字节解码为字符串、分离逻辑消息等),方法是使用pipeThrough
来转换数据。但是,一旦我这样做了,就不能再通过调用reader.releaseLock()
来释放端口上的锁了。我在这里做错什么了?
这段代码按照我预期的方式运行(在安全上下文中不依赖于浏览器):
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
也无法工作。
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
上的锁真的不会在上游传播吗?我是否必须跟踪每一个变压器在我的管道中的实例,这样我就可以确保全部解锁?
流规范说管道在管道操作期间锁定可读的和可写的流。
管道锁定可读和可写流,防止在管道操作期间对它们进行操作。这允许实现执行重要的优化,例如直接将数据从基础源传送到基础接收器,同时绕过许多中间队列。
我是否有其他方法表示“管道操作”已经完成?
发布于 2022-02-25 08:35:32
正如https://web.dev/serial/#close-port中所解释的,如果其readable
和writable
成员未锁定,则port.close()
将关闭串行端口,这意味着已经为它们各自的读取器和写入器调用了releaseLock()
。
但是,当使用转换流时,关闭串行端口要复杂一些。打电话给reader.cancel()
,然后打给writer.close()
和port.close()
。这会将错误通过转换流传播到基础串行端口。因为错误传播不会立即发生,所以需要使用先前创建的readableStreamClosed
和writableStreamClosed
承诺来检测port.readable
和port.writable
何时被解锁。取消读取器会导致流中止;这就是您必须捕获并忽略结果错误的原因。
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);
}
// 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();
https://stackoverflow.com/questions/71262432
复制相似问题