链接期货不按顺序执行

Rya*_*ler 0 dart dart-async flutter

我目前正在从蓝牙设备读取变量。这显然需要不确定的时间,所以我使用期货(这个方法在下面的代码中是 readCharacteristic )。

一次不能进行多个读取操作——如果在第一个操作仍在进行时启动了第二个读取操作,Flutter 将抛出错误。

我的理解是,使用 .then() 将期货链接在一起只会允许在前一个调用完成时执行下一个语句。这个想法似乎是正确的,直到我尝试读取第三个值——也就是当错误被抛出时,因为重叠的读取事件。

这是我的代码:

readCharacteristic(scanDurationCharacteristic)
    .then((list) => sensorScanDuration = list[0].toDouble())
    .then((_) {
  readCharacteristic(scanPeriodCharacteristic)
      .then((list) => sensorScanPeriod = list[0].toDouble());
}).then((_) {
  readCharacteristic(aggregateCharacteristic)
      .then((list) => sensorAggregateCount = list[0].toDouble());
}).then((_) {
  readCharacteristic(appEUICharacteristic)
      .then((list) => appEUI = decimalToHexString(list));
}).then((_) {
  readCharacteristic(devEUICharacteristic)
      .then((list) => devEUI = decimalToHexString(list));
}).then((_) {
  readCharacteristic(appKeyCharacteristic)
      .then((list) => appKey = decimalToHexString(list));
});
Run Code Online (Sandbox Code Playgroud)

确保这些读取事件不会重叠的更好方法是什么?

R. *_*ell 5

如果你想链接 Futures,你必须return从前一个 Future 的then方法中创建前一个 Future。

文档说像这样链接,

expensiveA()
    .then((aValue) => expensiveB())
    .then((bValue) => expensiveC())
    .then((cValue) => doSomethingWith(cValue));
Run Code Online (Sandbox Code Playgroud)

这与,

expensiveA()
    .then((aValue) {
        return expensiveB();
    }).then((bValue) {
        return expensiveC();
    }).then((cValue) => doSomethingWith(cValue));
Run Code Online (Sandbox Code Playgroud)

由于这适用于您的情况,

readCharacteristic(scanDurationCharacteristic)
    .then((list) {
        sensorScanDuration = list[0].toDouble();
        return readCharacteristic(scanPeriodCharacteristic);
    }).then((list) {
        sensorScanPeriod = list[0].toDouble());
        return readCharacteristic(aggregateCharacteristic);
    }).then((list) {
        sensorAggregateCount = list[0].toDouble());
        return readCharacteristic(appEUICharacteristic);
    }).then((list) {
        appEUI = decimalToHexString(list));
        return readCharacteristic(devEUICharacteristic);
    }).then((list) {
        devEUI = decimalToHexString(list));
        return readCharacteristic(appKeyCharacteristic);
    }).then((list) => appKey = decimalToHexString(list));
Run Code Online (Sandbox Code Playgroud)


Rém*_*let 5

尽管 RC Howell 的答案是正确的,但更喜欢使用async/await关键字。这更具可读性,您不太可能犯错误

Future<void> scanBluetooth() async {
  sensorScanDuration = (await readCharacteristic(scanDurationCharacteristic))[0].toDouble();
  sensorScanPeriod = (await readCharacteristic(scanPeriodCharacteristic))[0].toDouble();
  sensorAggregateCount = (await readCharacteristic(aggregateCharacteristic))[0].toDouble();
  appEUI = await readCharacteristic(appEUICharacteristic).then(decimalToHexString);
  devEUI = await readCharacteristic(devEUICharacteristic).then(decimalToHexString);
  appKey = await readCharacteristic(appKeyCharacteristic).then(decimalToHexString);
}
Run Code Online (Sandbox Code Playgroud)