链式期货不按顺序执行
Chaining Futures Do Not Execute In Order
我目前正在从蓝牙设备读取变量。这显然会花费不确定的时间,所以我正在使用期货(此方法在我下面的代码中为 readCharacteristic)。
一次不能进行多个读取操作 - 如果在第一个操作仍在进行时启动第二个读取操作,Flutter 将抛出错误。
我的理解是,使用 .then() 将 futures 链接在一起只会允许下一个语句在前一个调用完成时执行。这个想法似乎是正确的,直到我尝试读取第三个值 - 即由于重叠的读取事件而引发错误。
这是我的代码:
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));
});
确保这些读取事件不会重叠的更好方法是什么?
如果您想链接 Futures,您必须 return
来自前一个 Future 的 then
方法中的前一个 Future。
文档说要这样链接,
expensiveA()
.then((aValue) => expensiveB())
.then((bValue) => expensiveC())
.then((cValue) => doSomethingWith(cValue));
与
相同
expensiveA()
.then((aValue) {
return expensiveB();
}).then((bValue) {
return expensiveC();
}).then((cValue) => doSomethingWith(cValue));
由于这适用于您的情况,
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));
尽管 R.C 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);
}
我目前正在从蓝牙设备读取变量。这显然会花费不确定的时间,所以我正在使用期货(此方法在我下面的代码中为 readCharacteristic)。
一次不能进行多个读取操作 - 如果在第一个操作仍在进行时启动第二个读取操作,Flutter 将抛出错误。
我的理解是,使用 .then() 将 futures 链接在一起只会允许下一个语句在前一个调用完成时执行。这个想法似乎是正确的,直到我尝试读取第三个值 - 即由于重叠的读取事件而引发错误。
这是我的代码:
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));
});
确保这些读取事件不会重叠的更好方法是什么?
如果您想链接 Futures,您必须 return
来自前一个 Future 的 then
方法中的前一个 Future。
文档说要这样链接,
expensiveA()
.then((aValue) => expensiveB())
.then((bValue) => expensiveC())
.then((cValue) => doSomethingWith(cValue));
与
相同expensiveA()
.then((aValue) {
return expensiveB();
}).then((bValue) {
return expensiveC();
}).then((cValue) => doSomethingWith(cValue));
由于这适用于您的情况,
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));
尽管 R.C 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);
}