この質問は、ChromeシリアルAPIの使用時に発生した状況に関連していますが、おそらくすべてのReadableStreamに関連している可能性があります。私はドキュメントを調べましたが、おそらくいくつかの機能やパターンを見逃していました。
単純なプログラムがChromeブラウザーで実行され、CWキーヤーにアクセスします(Arduinoに基づいていますが、これは重要ではありません)。
アプリケーションはキーヤーにコマンドを送信し、応答として2つのバイナリバイトまたは文字列を期待します(特定の形式は送信されたコマンドに依存し、重要ではありません)。
シリアルデバイス(USB /シリアルアダプターではなく、Arduino)が何らかの理由でコマンドを見逃した場合、応答は送信されず、expectResponse()
以下の関数はデータを返すことも、例外をスローすることもありません。その結果、リーダーはロックされたままになるため、ReadableStreamを閉じることができず、その結果、シリアルポートも閉じることができません。
また、アプリケーションの構造によっては、他のコマンドがキーヤーに正常に送信された場合、最初のリーダーがストリームをブロックし、リリースされるまで新しいリーダーを作成できないため、2番目の応答を読み取ることができない場合があります。
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)で重要な何かを見逃したに違いないと確信していますが、解決策は見つかりませんでした。
実際のアプリのPSはserialPort
グローバル変数ですが、それは問題ではありませんか?
ReadableStream
タイムアウトが組み込まれているとは思いません。
私はPromise.race
あなたのタイムアウトである他の約束で使用します:
let { value, done } = await Promise.race([
reader.read(),
new Promise((_, reject) => setTimeout(reject, TIMEOUT, new Error("timeout")))
]);
(おそらくそのnew Promise
コードをユーティリティ関数に入れるでしょう。)
Promise.race
約束のレースを監視し、あなたが与えた配列の約束について最初に見た決済に基づいて約束を決済します。したがってread
、タイムアウトの約束が拒否される前に '約束が履行(または拒否)された場合、read
'の決済によってrace
約束の決済が決まります。それ以外の場合、race
PromiseはタイムアウトPromiseの決済(この場合は拒否)に基づいて決済されます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加