深入研究了dart 的异步事件执行流程。
main() {
/// testNoAwait() and testWithCallerAwait() exe order is same.
// testNoAwait();
// testWithCallerAwait();
/// testWithCalleeAwait() and testBothAwait() exe order is same;
// testWithCalleeAwait();
// testBothAwait();
/// testAllAwait() exe order is same as the code text order;
// testAllAwait();
}
testNoAwait() {
print('testNoAwait start…');
runNoAwait(delayedNoAwait, 10);
runNoAwait(delayedNoAwait, 5);
runNoAwait(delayedNoAwait, 1);
print('testNoAwait completed…\n');
}
testWithCallerAwait() {
print('testWithCallerAwait start…');
runWithAwait(delayedNoAwait, 10);
runWithAwait(delayedNoAwait, 5);
runWithAwait(delayedNoAwait, 1);
print('testWithCallerAwait completed…\n');
}
testWithCalleeAwait() {
print('testWithCalleeAwait start…');
runNoAwait(delayedWithAwait, 10);
runNoAwait(delayedWithAwait, 5);
runNoAwait(delayedWithAwait, 1);
print('testWithCalleeAwait completed…\n');
}
testBothAwait() {
print('testBothAwait start…');
runWithAwait(delayedWithAwait, 10);
runWithAwait(delayedWithAwait, 5);
runWithAwait(delayedWithAwait, 1);
print('testBothAwait completed…\n');
}
testAllAwait() async {
print('testAllAwait start…');
await runWithAwait(delayedWithAwait, 10);
await runWithAwait(delayedWithAwait, 5);
await runWithAwait(delayedWithAwait, 1);
print('testAllAwait completed…\n');
}
void runNoAwait(void delayed(int s), int seconds) {
delayed(seconds);
}
void runWithAwait(void delayed(int s), int seconds) async {
await delayed(seconds);
}
void delayedNoAwait(int s) {
print('delayedNoAwait $s start —');
Future.delayed(
Duration(seconds: s), () => print('delayedNoAwait $s task start…'))
.then((_) => print('delayedNoAwait $s task completed.'));
print('delayedNoAwait $s completed —\n');
}
void delayedWithAwait(int s) async {
print('delayedWithAwait $s start —');
await Future.delayed(Duration(seconds: s),
() => print('delayedWithAwait $s task start…'))
.then((_) => print('delayedWithAwait $s task completed.'));
print('delayedWithAwait $s completed —\n');
}
将 main() 中的注释逐行去掉,output 如下:
testNoAwait start…
delayedNoAwait 10 start —
delayedNoAwait 10 completed —
delayedNoAwait 5 start —
delayedNoAwait 5 completed —
delayedNoAwait 1 start —
delayedNoAwait 1 completed —
testNoAwait completed…
delayedNoAwait 1 task start…
delayedNoAwait 1 task completed.
delayedNoAwait 5 task start…
delayedNoAwait 5 task completed.
delayedNoAwait 10 task start…
delayedNoAwait 10 task completed.
Exited
testWithCallerAwait start…
delayedNoAwait 10 start —
delayedNoAwait 10 completed —
delayedNoAwait 5 start —
delayedNoAwait 5 completed —
delayedNoAwait 1 start —
delayedNoAwait 1 completed —
testWithCallerAwait completed…
delayedNoAwait 1 task start…
delayedNoAwait 1 task completed.
delayedNoAwait 5 task start…
delayedNoAwait 5 task completed.
delayedNoAwait 10 task start…
delayedNoAwait 10 task completed.
Exited
testWithCalleeAwait start…
delayedWithAwait 10 start —
delayedWithAwait 5 start —
delayedWithAwait 1 start —
testWithCalleeAwait completed…
delayedWithAwait 1 task start…
delayedWithAwait 1 task completed.
delayedWithAwait 1 completed —
delayedWithAwait 5 task start…
delayedWithAwait 5 task completed.
delayedWithAwait 5 completed —
delayedWithAwait 10 task start…
delayedWithAwait 10 task completed.
delayedWithAwait 10 completed —
Exited
testBothAwait start…
delayedWithAwait 10 start —
delayedWithAwait 5 start —
delayedWithAwait 1 start —
testBothAwait completed…
delayedWithAwait 1 task start…
delayedWithAwait 1 task completed.
delayedWithAwait 1 completed —
delayedWithAwait 5 task start…
delayedWithAwait 5 task completed.
delayedWithAwait 5 completed —
delayedWithAwait 10 task start…
delayedWithAwait 10 task completed.
delayedWithAwait 10 completed —
Exited
testAllAwait start…
delayedWithAwait 10 start —
delayedWithAwait 10 task start…
delayedWithAwait 10 task completed.
delayedWithAwait 10 completed —
delayedWithAwait 5 start —
delayedWithAwait 5 task start…
delayedWithAwait 5 task completed.
delayedWithAwait 5 completed —
delayedWithAwait 1 start —
delayedWithAwait 1 task start…
delayedWithAwait 1 task completed.
delayedWithAwait 1 completed —
testAllAwait completed…
Exited
通过仔细分析发现,异步执行虽然是个好东西,但当异步调用链过长时,如果不仔细检查代码,代码的执行顺序将很难预测正确。