每次滑块更改时如何通过蓝牙 LE 发送滑块值而不会出现垃圾邮件 "Transaction already in progress" 错误?

How can I send a slider value over Bluetooth LE every time the slider changes without spamming "Transaction already in progress" errors?

我在网站上使用 GUI 通过 BLE 控制电机的速度。每次滑块改变位置时,都会触发一个新的“oninput”事件。当您使用滑块时,这种情况大约会以 50x /sec 的速度发生。因为您一次只能发送一个 BLE 传输,而 BLE 传输需要大约 50 毫秒,所以有很多“交易已经在进行中”的错误。这导致最后几个输入丢失。当您从左向右快速滑动滑块时,步进电机将接收到该位置位于中间某处。我想要一个解决方案:

这是我的 hacky 解决方案:在输入时调用异步方法尝试发送值。如果它失败了,那么它会检查它是否失败,因为已经有另一个传输正在进行而不是其他错误。如果是这种情况,它会检查它尝试发送的值是否仍然是发送失败后的最新值。只有满足这两个条件,它才会调用自己并重试。

代码如下:

document.getElementById("sldSpeed").oninput = updateSpeed;
let speed = 0;
function updateSpeed() {
    speed = document.getElementById("sldSpeed").value;
    speed = parseInt(speed * 100);
    document.getElementById("lblSpeed").innerHTML = `${speed / 100} cm/s`;
    schrijfRealTimeSpeed(speed);
};

async function schrijfRealTimeSpeed(waarde) {
    schrijfUint32Value(karDelta, waarde)
        .catch((problem) => {
            if (problem.message === "GATT operation already in progress." & waarde === speed)
                schrijfRealTimeSpeed(waarde);
        });
}

(this schrijfUint32Value(karDelta, waarde) 调用 BLE 模块脚本中的方法并将数字转换为字节数组,然后 使用 Javascript BLE 函数 karakteristiek.writeValueWithResponse(byteArr) )

问题:我在滥用错误系统,这可能效率不高。 git 上的作者说,正确的方法是仅在先前的请求返回承诺后才发送新请求,这样您就不会一开始就收到“GAAT transmission in progress”错误。知道了这一点,是否有更清洁、更高效、更好、更像 javascript 的方法来解决这个问题?

这个对你有用吗

document.getElementById("sldSpeed").oninput = updateSpeed;
let speed = 0;
let firstrun = true;
let lastvalue = 0;
function updateSpeed() {
speed = document.getElementById("sldSpeed").value;
speed = parseInt(speed * 100);
document.getElementById("lblSpeed").innerHTML = `${speed / 100}cm/s`;
  if (firstrun == true)
  {
    firstrun = false;
    schrijfRealTimeSpeed(speed);
  }

}
async function schrijfRealTimeSpeed(waarde) {

   const realtimepromise = new Promise(async (resolve, reject) => {
   if (lastvalue!= waarde)
{
 lastvalue = waarde;
await schrijfUint32Value(karDelta, waarde);
resolve();
  } else
  {
  reject();
  firstrun = true;
    }
      });
  
   realtimepromise.then( (val) => schrijfRealTimeSpeed(speed));

   }

使用 Ignamuses 解决方案,我能够编写适用于我的应用程序的版本。我删除了一些承诺并添加了网络错误检查以防止无限循环:

let speed = 0;
let busy = false;
let speedLastTransmitted = 0;

document.getElementById("sldSpeed").oninput = updateSpeed;

function updateSpeed() {
    speed = document.getElementById("sldSpeed").value;
    speed = parseInt(speed * 100);
    document.getElementById("lblSpeed").innerHTML = `${speed / 100}cm/s`;
    if (busy === false) {
        busy = true;
        schrijfRealTimeSpeed(speed);
    }
}
async function schrijfRealTimeSpeed(waarde) {
    if (speedLastTransmitted === waarde)
        busy = false;
    else {
        schrijfUint32Value(karDelta, waarde)
            .then(() => {
                speedLastTransmitted = waarde;
                schrijfRealTimeSpeed(speed);
            })
            .catch((err) => {
                console.log(err)
            });
    }
}