我有一個 Web 串行埠,我想從中讀取一些資料。我想使用TransformStreams 來做一些處理(例如將位元組解碼為字串,分離出邏輯訊息等),通過使用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過去通過 do-nothing 發送輸出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"
}
What am I doing wrong here? Does releasing the lock on the TransformStream really not propagate upstream? Do I have to keep track of an instance of every transformer in my pipeline so I can be sure to unlock them all?
The streams spec says that piping locks the readable and writable streams for the duration of the pipe operation.
Piping locks the readable and writable streams, preventing them from being manipulated for the duration of the pipe operation. This allows the implementation to perform important optimizations, such as directly shuttling data from the underlying source to the underlying sink while bypassing many of the intermediate queues.
Is there some other way I have to indicate that the "piping operation" is completed?
uj5u.com熱心網友回復:
如https://web.dev/serial/#close-port中所述,如果串行埠和成員已解鎖,port.close()則關閉串行埠,這意味著它們各自的讀取器和寫入器已呼叫。readablewritablereleaseLock()
但是,在使用轉換流時,關閉串行埠會稍微復雜一些。呼叫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://www.uj5u.com/houduan/437403.html
