dart 非同步事件執行流程分析(二)
阿新 • • 發佈:2018-12-22
// 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';
void capture() async {
for (var i = 0; i < 5; i++) {
// captured.add(await emit());
emit().then((n) => captured.add(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 如下:
吐槽,為什麼每次程式碼粘貼後格式都亂了啊,還得重新格式化。
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); }); }
Future<int> emit() async { var n = rnd.nextInt(seed); emitted.add(n); await Future.delayed(Duration(seconds: n)); return n; }
藍色的兩行程式碼: // captured.add(await emit()); emit().then((n) => captured.add(n));
false
[2, 6, 1, 7, 4]
[1, 2, 4, 6, 7]
Exited
因此對於大型多次的非同步IO操作來說,恰當的使用then要比await高效的多。
吐槽,為什麼每次程式碼粘貼後格式都亂了啊,還得重新格式化。