Future と async/await
CoddyのDartジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 76/110。
実際のアプリケーションでは、サーバーからのデータの取得、ファイルの読み込み、ユーザー入力の待機など、多くの操作に時間がかかります。DartはこれらをFutureで処理します。これは、将来のある時点で利用可能になる値を表します。
Future はプロミス(約束)のようなものです:「準備ができたら結果を渡します」。Future.delayed() を使用して、時間のかかる操作をシミュレートすることで作成できます:
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}Futureの結果を扱うには、asyncとawaitを使用します。関数をasyncとしてマークし、awaitを使用してFutureが完了するまで実行を一時停止します:
Future<void> main() async {
print('Fetching user...');
String name = await fetchUserName();
print('Hello, $name!');
}
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}await なしでは、実際の文字列ではなく Future<String> を受け取ることになります。await キーワードは Future をアンラップし、その中の値を返します。await を使用する関数は async とマークされている必要があり、自動的に Future を返すことに注意してください。
async関数から直接値を返すこともできます。Dartはそれらを自動的にFutureでラップします:
Future<int> calculateTotal() async {
var a = await fetchNumber();
var b = await fetchNumber();
return a + b; // 自動的にFuture<int>でラップされます
}チャレンジ
簡単異なる都市の気象データを取得することをシミュレートする気象サービスを構築しましょう!完了までに時間がかかる操作を処理するために、Future、async、および await を使用する練習をします。
コードを2つのファイルに整理します:
weather_service.dart: 気象情報の取得をシミュレートするWeatherServiceクラスを作成します。クラスには以下を含める必要があります:Future<int>を返すメソッドfetchTemperature(String city)。ネットワーク遅延をシミュレートするために、100ミリ秒の期間でFuture.delayed()を使用します。このメソッドは、都市名に基づいた温度を返す必要があります。都市名の長さに3を掛けた値を返してください。Future<String>を返すメソッドfetchCondition(String city)。100ミリ秒の遅延でFuture.delayed()を使用します。都市名の文字数が偶数の場合は'Sunny'を返し、そうでない場合は'Cloudy'を返します。Future<String>を返す async メソッドgetFullReport(String city)。このメソッドはfetchTemperatureとfetchConditionの両方を await し、フォーマットされた文字列'[city]: [temperature]C, [condition]'を返す必要があります。
main.dart: 気象サービスをインポートし、非同期操作がどのように機能するかを示します。main 関数は async である必要があり、以下の処理を行います:WeatherServiceインスタンスを作成する'Fetching weather data...'とプリントする'Paris'のフルレポートを await してプリントする'Tokyo'のフルレポートを await してプリントする'London'のフルレポートを await してプリントする'Done!'とプリントする
getFullReport の各呼び出しが、結合された結果を返す前に、温度とコンディションの両方が取得されるのをどのように待機するかに注目してください。await キーワードは、各 Future が完了するまで実行を一時停止します!
期待される出力:
Fetching weather data...
Paris: 15C, Cloudy
Tokyo: 15C, Cloudy
London: 18C, Sunny
Done!チートシート
Future は、将来利用可能になる値を表します。データの取得やファイルの読み込みなど、時間のかかる操作に使用されます。
Future.delayed() を使用して Future を作成します:
Future<String> fetchUserName() {
return Future.delayed(
Duration(seconds: 1),
() => 'Alice',
);
}Future を扱うには async と await を使用します。関数を async としてマークし、await を使用して Future が完了するまで実行を一時停止します:
Future<void> main() async {
print('Fetching user...');
String name = await fetchUserName();
print('Hello, $name!');
}await キーワードは Future をアンラップし、実際の値を取得します。これがないと、文字列ではなく Future<String> を受け取ることになります。
await を使用する関数はすべて async とマークする必要があり、自動的に Future を返します。
async 関数からの戻り値は、自動的に Future でラップされます:
Future<int> calculateTotal() async {
var a = await fetchNumber();
var b = await fetchNumber();
return a + b; // 自動的に Future<int> でラップされます
}自分で試してみよう
import 'weather_service.dart';
Future<void> main() async {
// TODO: WeatherService インスタンスを作成する
// TODO: 'Fetching weather data...' と出力する
// TODO: 'Paris' の完全なレポートを await して出力する
// TODO: 'Tokyo' の完全なレポートを await して出力する
// TODO: 'London' の完全なレポートを await して出力する
// TODO: 'Done!' と出力する
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4Null Safety
Null Safety 入門Nullable と Non-Nullable? 演算子と ! 演算子late キーワードと Null SafetyNull-Aware 演算子クラスにおける Null Safetyまとめ:ユーザープロフィールシステム10コレクションとジェネリクス
List, Set, Map の概要型安全なコレクションジェネリッククラスジェネリックメソッドジェネリクスの制約Iterable と Iteratorまとめ:ジェネリックなストレージ12非同期 OOP
Future と async/awaitStream の基礎Stream Controller非同期コンストラクタクラスメソッドにおける非同期処理まとめ - Data Fetcher