Web Serial API:如何刷新缓冲区、获取数据长度及检测输入流数据
Web Serial API 相关问题解答
一、如何检测输入流(port.readable)中是否存在可用数据?
SerialPort.readable 属性仅表示当前串口处于可读取状态,无法直接通过它判断缓冲区中是否有等待读取的数据。要检测可用数据,需通过流读取器尝试读取:
- 先确认
port.readable不为null,说明串口当前支持读取操作; - 创建流读取器(
ReadableStreamDefaultReader或ReadableStreamBYOBReader); - 调用
reader.read()方法,该方法返回 Promise:- 若解析结果中
done为false,则value为读取到的二进制数据,说明缓冲区有可用数据; - 若
done为true,则当前缓冲区无数据。
- 若解析结果中
示例代码(检测且保留数据)
如果仅做检测不想消费数据,需将读取到的数据放回流中,避免后续读取丢失:
async function hasAvailableData(port) { if (!port.readable) return false; const reader = port.readable.getReader(); try { const { value, done } = await reader.read(); if (done) return false; // 将读取到的数据放回流 reader.releaseLock(); port.readable = new ReadableStream({ start(controller) { controller.enqueue(value); port.readable.pipeTo(controller, { preventClose: true }); } }); return true; } catch (err) { reader.releaseLock(); return false; } }
如果不需要保留数据,直接读取丢弃即可完成检测。
二、如何刷新缓冲区?
刷新缓冲区的核心是清空串口接收缓冲区中未读取的数据,两种常用方式需根据场景选择:
方式1:循环读取至缓冲区为空(推荐,保留流可用性)
若希望清空后仍能继续读取数据,可循环调用 reader.read() 直到返回 done: true,将缓冲区所有数据读取并丢弃:
async function flushBuffer(port) { if (!port.readable) return; const reader = port.readable.getReader(); try { while (true) { const { done } = await reader.read(); if (done) break; // 读取到的数据直接丢弃,不做处理 } } catch (err) { // 处理读取错误 } finally { reader.releaseLock(); } }
该方式不会终止流,完成后可重新获取读取器继续读取后续数据。
方式2:调用 reader.cancel()(终止当前读取流)
若无需继续使用当前读取流,可调用 reader.cancel() 终止读取并清空缓冲区,但会同时关闭当前 ReadableStream。后续若要再次读取,需等待 port.readable 重新变为可用:
async function cancelAndFlush(port) { if (!port.readable) return; const reader = port.readable.getReader(); try { await reader.cancel(); // 取消后 port.readable 会变为 null,需等待串口重新触发可读状态 } catch (err) { // 处理取消错误 } finally { reader.releaseLock(); } }
该方式适合不再需要读取数据,或需彻底重置流的场景。
内容的提问来源于stack exchange,提问作者handle
相关产品推荐
相关产品推荐

