dart 异步事件执行流程分析(二)

// use two list to test the async envet exe order.
// one record the emitted order;
// and the other record the captured order;
import 'dart:math';
final rnd = Random();
final seed = 10;
final emitted = <int>[];
final captured = <int>[];
main() {
capture();
Future.delayed(Duration(seconds: 50), () { // to wait capture() over
print(isEqual(emitted, captured));
print(emitted);
print(captured);
});
}
void capture() async {
for (var i = 0; i < 5; i++) {
   // captured.add(await emit());
  emit().then((n) => captured.add(n));
  }
}
Future<int> emit() async {
var n = rnd.nextInt(seed);
emitted.add(n);
await Future.delayed(Duration(seconds: n));
return n;
}
bool isEqual(List<int> a, List<int> b) {
if (a.length != b.length) return false;
for (var i = 0; i < a.length; i++) {
  if (a[i] != b[i]) return false;
}
return true;
}

蓝色的两行代码:
   // captured.add(await emit());
  emit().then((n) => captured.add(n));
如果注释掉下面一行,执行上面一行,则两个list:emitted and captured的结果是一致的。await 起到了每一次emit的等待作用,代码顺序执行,但花费的总时间是串行的总时间之和,即O(Σ(n));
 
但如果把上面一行注释掉,执行下面一行,则两个list的结果就是不同的。因为在下面一行then的回调中,经过测试发现,dart的异步 event loop不是顺序执行的。比如例子中5次emit(),根据生产的随机数delay,则随机delay时间最短的任务先完成,先调用在then()函数中注册的回调函数,因此captured中添加元素的顺序就和emit()发射的不一致,花费的时间是最大的delay的时间,即O(max(n))。output 如下:

false
[2, 6, 1, 7, 4]
[1, 2, 4, 6, 7]
Exited

因此对于大型多次的异步IO操作来说,恰当的使用then要比await高效的多。

 

吐槽,为什么每次代码粘贴后格式都乱了啊,还得重新格式化。

猜你喜欢

转载自www.cnblogs.com/pacific/p/10159562.html