こんにちは。Flutterでは切っても切り離せないFutureのお話。
世界中の老若男女が考えるであろう、
「Futureめんどいから、もうそのまま実行してくれね?」
という願望。私も常々そう思い、ことある毎にGoogle巡礼しています。その中でよく目にする、即時関数やその他その場で実行している感のあるスクリプト。
用途によっては全然良いのですが、場合によってはやばいかも知れません。
前置き。awaitできないケース
色々ありますが、例えばコンストラクタではawait出来ません。
やっちまったCase1: Futureの中でasync awaitする
次の例を見てください。
main() {
Future(() async {
await Future.delayed(Duration(seconds: 1));
print("future");
});
print("now");
}
私は最初これを見た時、歓喜に打たれてオレンジジュースを飲み干しました。Futureめんどい問題が見事に解決されている、awaitも入っているので、きっとfutureが先に出力されて、その後にnowが来るだろう。そう思ってオレンジジュースを注ぎました。実際に動かしてみると、結果は次のようになります。
now
future
なぜでしょう。
原因
Futureに渡している関数自体はasyncです。これは非同期ですので、実装は知りませんが、概念的には別スレッドで飛び立って、残されたスレッドは粛々と次の作業に移るわけですね。この非同期を繋ぎ止めるのがawaitですが、このスクリプト、awaitはasyncの中にしかありません。つまり別スレッドとして飛び立ったあと、その中でawaitしているわけです。これでは、普通の非同期と変わりありませんね。
やっちまったCase2: 即時関数でやっちまう
次の例を見てください。
main() {
() async {
await Future.delayed(Duration(seconds: 1));
print("future");
}();
print("now");
}
now
future
これも同じです。即時関数ですぐに実行しているので、非同期から解放されて地に足のついた感がありますが、実はまだ非同期です。先程と同様、awaitが中に入っているだけですので、即時関数自体は非同期になっています。
終わりに
いかがでしたでしょうか。ちなみに私はFlutter赤ん坊ですので、間違いなどあるかも知れません。ご指摘いただけましたら幸いです。
以上です。