setTimeout函数触发两次回调

问题描述

我有一个功能,基本上将数据添加到队列中,每500毫秒发送一次数据,并且我使用了setTimeouts来写数据,如下所示。而且我怀疑setTimeout的分析日志已被调用两次,我想知道是否有可能?可能的解决方法是什么?


import BleManager from 'react-native-ble-manager';

const BleManagerModule = NativeModules.BleManager;
const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);

class bleHandler {
constructor() {
    this.writeQueue = [];
    bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic',this.handleUpdateValueForCharacteristic);
}

//this function will be called when ble receives data from peripheral.
handleUpdateValueForCharacteristic(data){
   // do something with data
   //send ack that data is received.
   this.writeData("AB:CD:EF:GH:IJ"," Some Important Message text ");
}

 writeData(peripheralID,data) {
    console.log("Adding data to Queue " + data);
    if (this.writeQueue.length == 0) {
      this.writeQueue.push(data);
      setTimeout(() => this.sendData(peripheralID,data),500);
    } else
      this.writeQueue.push(data);

    console.log("New Queue Length = " + this.writeQueue.length);
  }

  sendData = (peripheralID,data) => {
    if (data.length > 0 && peripheralID && this.writeQueue.length > 0) {
      var byteBuf = this.formatData(data);
console.log("============" + slicedData + " and length = " + slicedData.length + " at Date = " + new Date().valueOf());
console.log("Writing Message : " + byteBuf );
      this.handleWriteWithoutResponse(peripheralID,UUID,CHAR,byteBuf).then(() => {
        console.log("success writing data ");

        data = data.substring(PACKET_SIZE - 5);
        if (data.length > 0) {
          setTimeout(() => {
            this.writeQueue[0] = data;
            this.sendData(peripheralID,data)
          },500);
        } else {
          this.writeQueue.shift();
          setTimeout(() => {
            if (this.writeQueue.length > 0)
              this.sendData(peripheralID,this.writeQueue[0]);
          },500);
        }
      }).catch((error) => {
        console.log("error writing data ",error);
      });
    }
  }
}
const bleModule = new bleHandler();
export default bleModule;

日志

11:13:28 log Adding data to Queue " Some Important Message text "
11:13:28 log New Queue Length = 1
11:13:28 log ============" Some Important Message text " and length = 28 at Date = 1597680808275
11:13:28 log Writing Message : 9876543211223A2243222C202233223A7B2241636B223A223230302212345
11:13:28 log ============" Some Important Message text " and length = 28 at Date = 1597680808276
11:13:28 log Writing Message : 9876543211223A2243222C202233223A7B2241636B223A223230302212345
11:13:28 log success writing data 
11:13:28 log success writing data 

现在,如果您查看IOS中的日志,我发现发送数据在(1597680808276-1597680808275)1 ms间隔内两次被调用,并且它是通过setTimeout函数调用的。 js中的setTimeout是否有问题?还是反应性问题或野生动物园问题?以及如何解决此问题。我已经看到几年前在nodejs中修复的类似问题。

注意:我正在使用react-native-ble-manager来发送/接收数据。

解决方法

此问题的根本原因是由于函数sendData自身的调用。

sendData = (peripheralID,data) => {
  if (data.length > 0 && peripheralID && this.writeQueue.length > 0) {
    // ... 
    if (data.length > 0) {
      setTimeout(() => {
      // ...
      this.sendData(peripheralID,data)                      ---> Recursive call
      },500);
    } else {
      // ...
      setTimeout(() => {
        if (this.writeQueue.length > 0)
          this.sendData(peripheralID,this.writeQueue[0]);   ---> Recursive call
        },500);
      }
    // ...
  }

多次调用sendData的问题可以通过删除递归来解决

在此示例中,两个定时器回调(均计划在500ms之后发生)快速连续到达:

function example(a) {
    console.log("example:",a,"at",Date.now());
    if (a <= 3) {
        setTimeout(() => {
            example(a * 2);
        },500);
    }
}
// Schedule the calls
example(2);
example(3);

// Keep the thread busy
const end = Date.now() + 600;
while (Date.now() < end) {
}

注意如何

example: 4 at 1597923771329
example: 6 at 1597923771330

在时间上彼此紧邻。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...