This question is related to a situation that occurred when using Chrome Serial API but probably could be relevant to any ReadableStream. I studied the documentation and probably missed some feature or pattern.
A simple program is running in Chrome browser, accessing CW keyer (based on Arduino, but this is not important).
The application sends a command to the keyer and expects two binary bytes or a string as a response (particular format depends on the command sent and is not important).
In case that the serial device (not the USB/serial adapter, but the Arduino) misses the command for whatever reason, response is never sent and the function expectResponse()
below will never return any data, nor will it throw any exception. As a result, the Reader remains locked, the ReadableStream therefore cannot be closed and as a consequence, the serial port cannot be closed either.
Also, depending on the application structure, in case of other command sent successfully to the keyer, it may be not possible to read the second response because the first reader blocks the stream and until it is released, new Reader cannot be created.
async function expectResponse( serialPort ) {
const reader = serialPort.readable.getReader() ;
let { value, done } = await reader.read() ; // this never returns because no data arrive, not possible to "break"
}
async function disconnect( serialPort ) {
// ... some cleanup ...
// naive attempt to unlock ReadableStream before closing
await serialPort.readable.getReader().releaseLock() // this will throw exception - cannot create new reader while another one is still active and locks the stream
// ...
await serialPort.close(); // this will throw exception - cannot close port because readable stream is locked
}
serialPort
is the object returned by navigator.serial.requestPort()
I am convinced I must have missed something important in API docs (ReadableStream
or Reader
API, not Serial
API), but I did not find solution.
P.S. in the real app serialPort
is a global variable, but it does not matter, does it?