"DOMException: A buffer overrun has been detected"但前提是USB串行端口保持连接状态一段时间?



我有一个React应用程序,在那里我使用UART电缆从微控制器读取数据。微控制器正在连续打印JSON字符串。应用程序解析此字符串并显示其值。

来自我的微控制器的JSON字符串如下所示:

{"addr":"00xxxxxxxxxxxxxx","1":{"type":"a","value":40.7}}

我关注了这篇博客文章来帮助我做到这一点,并使用了一个TransformStream,它与博客文章中使用的LineBreakTransformer相同,这样我就可以解析一个完整的JSON字符串。我有一个按钮可以在点击时触发这一切。

以下是我面临的问题:如果我插入USB并快速按下按钮,一切都会正常工作。我收到提示,要求我选择正确的COM端口,我接收数据,并能够解析它。然而,如果我插入USB,并在按下按钮前放置一段时间,我会得到COM端口提示,但随后会出现以下错误:

Uncaught (in promise) DOMException: A buffer overrun has been detected.
Uncaught (in promise) TypeError: Failed to execute 'pipeTo' on 'ReadableStream': Cannot pipe a locked stream

此外,当我收到这个错误时,在刷新屏幕并快速按下按钮后,它成功地工作了。

为什么会发生这种情况,我该如何解决?

谢谢。

源代码:

import React, { useState } from 'react'
class LineBreakTransformer {
constructor() {
this.chunks = ''
}
transform(chunk, controller) {
this.chunks += chunk
const lines = this.chunks.split('rn')
this.chunks = lines.pop()
lines.forEach((line) => controller.enqueue(line))
}
flush(controller) {
controller.enqueue(this.chunks)
}
}
const App = () => {
const [macAddr, setMacAddr] = useState('')
const [sensors, setSensors] = useState([])
async function onButtonClick() {
const port = await navigator.serial.requestPort()
await port.open({ baudRate: 115200, bufferSize: 10000000 })
while (port.readable) {
// eslint-disable-next-line no-undef
const textDecoder = new TextDecoderStream()
port.readable.pipeTo(textDecoder.writable)
const reader = textDecoder.readable.pipeThrough(new TransformStream(new LineBreakTransformer())).getReader()
try {
while (true) {
const { value, done } = await reader.read()
if (done) {
reader.releaseLock()
break
}
if (value) {
const { addr, ...sensors } = JSON.parse(value)
setMacAddr(addr)
setSensors(sensors)
}
}
} catch (error) {}
}
}
return (
<div>
<h1>{`macAddr: ${macAddr}`}</h1>
{Object.keys(sensors).map((sensor) => (
<div key={sensor}>
<div>{`Channel: ${sensor}`}</div>
<div>{`Temp: ${sensors[sensor].value}`}</div>
</div>
))}
<button
onClick={async () => {
await onButtonClick()
}}
>
CLick
</button>
</div>
)
}
export default App

问题是,无论主机是否准备好接收数据,您的设备都在发送数据。计算机中的UART(如果是USB串行转换器,则在电缆中(的数据缓冲空间有限。如果溢出,则会得到所看到的错误。这是一个可恢复的错误。如果你抓住它并再试一次,只要port.readable是真的,它就会清除错误,并给你一个新的ReadableStream,你可以用来继续阅读。请注意,一些初始数据会因为溢出而损坏。

好吧,伙计们,我发现我做错了什么。这个问题与等待无关。这个问题实际上是在JSON.parse()上。

由于我正在读取流,偶尔我不会得到完整的数据包,只会得到微控制器发送的JSON字符串的剩余部分(例如,只有:1}而不是{"a":1}。当我插入设备后立即开始读取时,这种情况发生的可能性较小。

当我解析它时,我的函数会出错,因为它不是有效的JSON。由于我有一个while循环,它在port.readable.pipeTo(textDecoder.writable)失败,因为读取器被锁定。

我通过将parse()封装在try-catch块中来解决这个问题。

最新更新