Web Serial API无法稳定读取全部数据,请求技术解决方案
Web Serial API 数据读取异常问题
使用Web Serial API时遇到数据读取异常:有时能完整读取数据,有时会中途停止,无法获取全部数据。希望实现releaseLock后总能读取全部数据,以下是读写代码:
async function writeSerial_BMSA() { try { writer = port.writable.getWriter(); let commandframe = new Uint8Array([ 0x42, 0x4D, 0x53, 0x41, ]); commandframe = NACTRAU_Send(commandframe); await writer.write(commandframe); log.innerHTML = commandframe; writer.releaseLock(); write_times++; } catch (error) { log.innerHTML = error; } }
async function readSerial_BMSA() { try { reader = port.readable.getReader(); try { while (true) { const { value, done } = await reader.read(); if (done) { reader.releaseLock(); break; } if (value.length > 1) { let FWV = ""; let U_len = value[2] - 4; for (let i = 0; i < U_len; i++) { value[i] = value[i + 6]; FWV += String.fromCharCode(value[i]); } read_times++; break; } } } catch (error) { console.error(error); log.innerHTML = error; } finally { console.log(port.readable); reader.releaseLock(); } } catch (error) { log.innerHTML = error; } }
已尝试将处理代码放入if (done){}中,但未解决问题。
预期正确读取结果:
new Uint8Array([49, 48, 45, 48, 55, 45, 66, 44, 65, 117, 103, 32, 50, 55, 32, 50, 48, 50, 49, 32, 49, 56, 58, 52, 56, 58, 50, 53, 32, 44, 48, 50, 48, 55, 44, 56, 48, 50, 48, 44, 49, 48, 44, 48, 50, 44, 49, 48, 44, 48, 50, 74, 226])
错误读取结果示例:
new Uint8Array([49, 48, 45, 48, 55, 45, 66, 44, 65, 117, 103, 32, 50, 55, 32, 50, 48, 50, 49, 32, 49, 0, 0, 0, 0, 0, 0])
问题分析与修复方案
你的读取逻辑有两个核心问题:
- 单次读取后直接中断循环:Web Serial API的
read()是分批返回数据的,设备不会一次性发送所有内容,当前代码读取到第一块数据就break,自然拿不到完整内容。 - 未按协议拼接完整数据:依赖单次读取的
value[2]计算长度,若第一块数据不包含完整长度字段或后续数据未接收完,会导致长度计算错误,读取到无效的0填充数据。
修复后的代码会先拼接所有接收的数据,直到满足协议规定的完整条件再处理:
async function readSerial_BMSA() { try { const reader = port.readable.getReader(); let receivedData = new Uint8Array(); try { while (true) { const { value, done } = await reader.read(); if (done) { break; } // 拼接新接收的数据 const temp = new Uint8Array(receivedData.length + value.length); temp.set(receivedData); temp.set(value, receivedData.length); receivedData = temp; // 根据协议判断是否接收完整:第3个字节(索引2)为总长度 if (receivedData.length >= 3) { const totalLength = receivedData[2]; if (receivedData.length >= totalLength) { // 处理完整数据 let FWV = ""; const U_len = totalLength - 4; for (let i = 0; i < U_len; i++) { FWV += String.fromCharCode(receivedData[i + 6]); } read_times++; break; } } } } catch (error) { console.error(error); log.innerHTML = error; } finally { reader.releaseLock(); } } catch (error) { log.innerHTML = error; } }
额外优化建议
- 改用局部变量:避免全局的
reader/writer引发锁冲突,修复代码中已改为函数内局部变量。 - 添加超时机制:防止设备无响应导致读取逻辑挂起,可在循环中加入超时判断,超时后终止读取并释放锁。
- 数据完整性校验:根据设备协议添加CRC等校验逻辑,确保接收的数据未出错。
内容的提问来源于stack exchange,提问作者Vince
相关产品推荐
相关产品推荐

