メインコンテンツにスキップ

非同期プログラミング

Dart のライブラリには、Future または Stream オブジェクトを返す関数が多数あります。これらの関数は*非同期*です。つまり、時間のかかる可能性のある操作(I/O など)のセットアップ後に、その操作が完了するのを待たずに返します。

async および await キーワードは非同期プログラミングをサポートしており、同期コードに似た非同期コードを記述できます。

Future の処理

#

完了した Future の結果が必要な場合は、2 つの選択肢があります。

async および await を使用するコードは非同期ですが、同期コードによく似ています。たとえば、非同期関数の結果を待つために await を使用するコードを次に示します。

dart
await lookUpVersion();

await を使用するには、コードは async 関数内にある必要があります。これは async としてマークされた関数です。

dart
Future<void> checkVersion() async {
  var version = await lookUpVersion();
  // Do something with version
}

await を使用するコードでエラーを処理し、クリーンアップするには、trycatch、および finally を使用します。

dart
try {
  version = await lookUpVersion();
} catch (e) {
  // React to inability to look up the version
}

async 関数内で await を複数回使用できます。たとえば、次のコードは関数の結果を 3 回待機します。

dart
var entrypoint = await findEntryPoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);

await expression では、expression の値は通常 Future です。そうでない場合は、値は自動的に Future にラップされます。この Future オブジェクトは、オブジェクトを返すことを約束します。await expression の値は、その返されたオブジェクトです。await 式は、そのオブジェクトが利用可能になるまで実行を一時停止します。

await を使用するときにコンパイル時エラーが発生した場合は、awaitasync 関数内にあることを確認してください。たとえば、アプリの main() 関数で await を使用するには、main() の本体を async としてマークする必要があります。

dart
void main() async {
  checkVersion();
  print('In main: version is ${await lookUpVersion()}');
}

Future、async、および await の使用に関するインタラクティブな入門については、非同期プログラミングチュートリアルを参照してください。

async 関数の宣言

#

async 関数とは、本体が async 修飾子でマークされた関数です。

関数に async キーワードを追加すると、その関数は Future を返すようになります。たとえば、String を返す次の同期関数を考えてみましょう。

dart
String lookUpVersion() => '1.0.0';

(将来の実装に時間がかかる可能性があるため)それを async 関数に変更すると、返される値は Future になります。

dart
Future<String> lookUpVersion() async => '1.0.0';

関数の本体で Future API を使用する必要がないことに注意してください。Dart は必要に応じて Future オブジェクトを作成します。関数が有用な値を返さない場合は、戻り値の型を Future<void> にします。

Future、async、および await の使用に関するインタラクティブな入門については、非同期プログラミングチュートリアルを参照してください。

Stream の処理

#

Stream から値を取得する必要がある場合は、2 つの選択肢があります。

  • async および*非同期 for ループ* (await for) を使用します。
  • dart:async ドキュメントで説明されている Stream API を使用します。

非同期 for ループは次の形式をとります。

dart
await for (varOrType identifier in expression) {
  // Executes each time the stream emits a value.
}

expression の値は Stream 型でなければなりません。実行は次のように進みます。

  1. Stream が値を発行するまで待機します。
  2. for ループの本体を実行します。変数はその発行された値に設定されます。
  3. Stream が閉じられるまで 1 と 2 を繰り返します。

Stream のリッスンを停止するには、break または return ステートメントを使用できます。これにより、for ループが終了し、Stream から購読解除されます。

非同期 for ループを実装するときにコンパイル時エラーが発生した場合は、await forasync 関数内にあることを確認してください。たとえば、アプリの main() 関数で非同期 for ループを使用するには、main() の本体を async としてマークする必要があります。

dart
void main() async {
  // ...
  await for (final request in requestServer) {
    handleRequest(request);
  }
  // ...
}

Dart の非同期プログラミングサポートの詳細については、dart:async ライブラリのドキュメントを確認してください。