內容

非同步支援

Dart 函式庫中充斥著會傳回 FutureStream 物件的函式。這些函式是非同步的:它們會在設定可能耗時的作業(例如 I/O)後傳回,而不會等到作業完成。

asyncawait 關鍵字支援非同步程式設計,讓您可以撰寫看起來類似同步程式碼的非同步程式碼。

處理 Future

#

當您需要已完成 Future 的結果時,您有兩個選項

使用 asyncawait 的程式碼是非同步的,但它看起來很像同步程式碼。例如,以下是使用 await 來等待非同步函式結果的一些程式碼

dart
await lookUpVersion();

要使用 await,程式碼必須在 async 函式中,也就是標記為 async 的函式

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

使用 trycatchfinally 來處理使用 await 的程式碼中的錯誤和清理

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

您可以在 async 函式中多次使用 await。例如,下列程式碼等待函式的結果三次

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() 函式中使用 awaitmain() 的主體必須標記為 async

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

如需使用 future、asyncawait 的互動式簡介,請參閱 非同步程式設計 codelab

宣告非同步函式

#

async 函式是一個主體標記為 async 修飾詞的函式。

async 關鍵字新增到函式會讓它傳回 Future。例如,考慮這個傳回字串的同步函式

dart
String lookUpVersion() => '1.0.0';

如果您將它變更為 async 函式,例如因為未來的實作會很耗時,傳回的值會是 Future

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

請注意,函式的本體不需要使用 Future API。Dart 會在必要時建立 Future 物件。如果你的函式沒有傳回有用的值,請將其傳回類型設為 Future<void>

如需使用 future、asyncawait 的互動式簡介,請參閱 非同步程式設計 codelab

處理串流

#

當你需要從串流取得值時,你有兩個選項

  • 使用 async 和非同步 for 迴圈 (await for)。
  • 使用串流 API,如 dart:async 文件 中所述。

非同步 for 迴圈的格式如下

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

expression 的值必須是 Stream 類型。執行程序如下

  1. 等待串流發出一個值。
  2. 執行 for 迴圈的本體,其中變數設定為發出的值。
  3. 重複 1 和 2,直到串流關閉。

若要停止監聽串流,你可以使用 breakreturn 陳述式,這會中斷 for 迴圈並取消串流訂閱。

如果你在實作非同步 for 迴圈時遇到編譯時間錯誤,請確認 await forasync 函式中。例如,要在應用程式的 main() 函式中使用非同步 for 迴圈,main() 的本體必須標記為 async

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

有關 Dart 非同步程式設計支援的更多資訊,請查看 dart:async 函式庫文件。