Search code examples
dartflutterdart-async

Chaining Futures Do Not Execute In Order


I'm currently reading variables from a Bluetooth device. This obviously takes an undetermined amount of time, so I am using futures (This method is readCharacteristic in my code down below).

More than one read operation cannot take place at a time - if a second read operation is started while a first operation is still in progress, Flutter will throw an error.

My understanding was that chaining futures together using .then() would only allow the next statement to execute when the previous call had finished. This idea seems to be true until I try to read a third value - that is when the error is thrown, because of the overlapping read events.

Here is my code:

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));
});

What is a better way to ensure that these read events will not overlap?


Solution

  • Although R.C Howell answer is correct, prefer using async/await keywords instead. This is much more readable and you're less likely to make an error

    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);
    }