此问题与使用Chrome串行API时发生的情况有关,但可能与任何ReadableStream相关。我研究了文档,可能错过了一些功能或模式。
一个简单的程序在Chrome浏览器中运行,访问CW键控器(基于Arduino,但这并不重要)。
应用程序向键控器发送命令,并期望两个二进制字节或一个字符串作为响应(特定格式取决于发送的命令,并不重要)。
如果串行设备(不是USB/串行适配器,而是Arduino)由于任何原因错过了命令,则永远不会发送响应,并且下面的函数expectResponse()
永远不会返回任何数据,也不会抛出任何异常。因此,阅读器保持锁定,ReadableStream因此无法关闭,因此串行端口也无法关闭。
此外,取决于应用结构,在其他命令成功发送到键控器的情况下,可能无法读取第二响应,因为第一读取器阻止流,并且直到它被释放,才能创建新的读取器。
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
是navigator.serial.requestPort()
返回的对象
我确信我一定错过了API文档中的一些重要内容(ReadableStream
或Reader
API,而不是Serial
API),但我没有找到解决方案。
P.S.在真实的应用程序中serialPort
是一个全局变量,但这并不重要,不是吗?
2条答案
按热度按时间fivyi3re1#
我不认为
ReadableStream
内置了超时。我会使用
Promise.race
,另一个promise是你的timeout:new Promise
代码放在一个实用程序函数中。)*Promise.race
监视promise的竞争,根据它给予的数组中promise的第一个结算来结算它的promise。因此,如果read
的promise在timeout promise拒绝之前被满足(或拒绝),则read
的结算决定race
promise的结算。否则,race
promise将根据timeout promise的结算(在本例中为rejection)进行结算。mpbci0fu2#
可以“中断”await操作:
根据文档,如果调用
reader.releaseLock()
,await reader.read()
将抛出TypeError
。(例如setTimeout
)文档:https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader/read