Dartの非同期周りの挙動や使用どころについてのメモ。
基本的にDart(Flutter)はシングルスレッドで実装して、どうしても重い処理はIsolateやComputeを使用して別スレッドで処理することになる。
ただ単純なシングルスレッドだとネットワークレスポンスを待ったりする間にUIが固まってしまうので、Dartではイベントループを使用して非同期処理を実現している。
非同期処理の方法がasync,await,then辺りであり、それぞれの使い所や挙動の違いをまとめた。
async, await, thenの使い所
- async: 非同期メソッドを定義する場合に使用する
- await: 非同期メソッドの実行を待ってから以降の処理をしたい場合に使用する
- then: 非同期メソッドの実行結果のコールバックを受け取って処理したい場合に使用する
- thenの外に記述された処理はコールバックを待たずに実行されていく
動作検証
コード
void main() async {
print("001");
returnTwo().then((value) {
print(value);
});
print("003");
var value = await returnFour();
print(value);
print("005");
}
Future<String> returnTwo() async {
print("returnTwo");
await Future.delayed(Duration(seconds: 2));
return "002";
}
Future<String> returnFour() async {
print("returnFour");
await Future.delayed(Duration(seconds: 2));
return "004";
}
実行結果
001
returnTwo
003
returnFour
002
004
005
解説
① 001: 普通に順番通り出力される
② returnTwo: returnTwo()がコールされてawaitされる前なので出力される
③ 003: main()が進んでいき003が出力される
④ returnFour: returnFour()がコールされてawaitされる前なので出力される
⑤ 002: returnTwo()の待ちが終了して002が出力される
⑥ 004: returnFour()の待ちが終了して004が出力される
⑦ 005: mainが進んでいき005が出力される
ポイント
② returnTwo()全体の実行が待たれるのではなくreturnTwo()内で待ちが発生する処理までは同期的に実行される
③ returnTwo()内部で待ちが発生するとmain()は進んでいく
⑦ main()はreturnFour()をawaitしているのでreturnFour()が完了するまで処理は進んでいかない
参考
https://medium.com/@jelenaaa.lecic/when-to-use-async-await-then-and-future-in-dart-5e00e64ab9b1
https://medium.com/@kawanojieee/dart-async-await-394846fb3d2c
https://medium.com/flutter-jp/isolate-a3f6eab488b5