Dart 庫中包含許多返回 Future 或 Stream 對象的函數(shù). 這些函數(shù)在設(shè)置完耗時任務(wù)(例如 I/O 曹組)后, 就立即返回了,不會等待耗任務(wù)完成。 使用 async 和 await 關(guān)鍵字實現(xiàn)異步編程。 可以讓你像編寫同步代碼一樣實現(xiàn)異步操作。
可以通過下面兩種方式,獲得 Future 執(zhí)行完成的結(jié)果:
使用 async 和 await 關(guān)鍵字的代碼是異步的。 雖然看起來有點像同步代碼。 例如,下面的代碼使用 await 等待異步函數(shù)的執(zhí)行結(jié)果。
await lookUpVersion();
要使用 await , 代碼必須在 異步函數(shù)(使用 async 標記的函數(shù))中:
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
提示: 雖然異步函數(shù)可能會執(zhí)行耗時的操作, 但它不會等待這些操作。 相反,異步函數(shù)只有在遇到第一個 await 表達式(詳情見)時才會執(zhí)行。 也就是說,它返回一個 Future 對象, 僅在await表達式完成后才恢復(fù)執(zhí)行。
使用 try, catch, 和 finally 來處理代碼中使用 await 導(dǎo)致的錯誤。
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
在一個異步函數(shù)中可以多次使用 await 。 例如,下面代碼中等待了三次函數(shù)結(jié)果:
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
在 await 表達式 中, 表達式 的值通常是一個 Future 對象; 如果不是,這是表達式的值會被自動包裝成一個 Future 對象。 Future 對象指明返回一個對象的承諾(promise)。 await 表達式 執(zhí)行的結(jié)果為這個返回的對象。 await 表達式會阻塞代碼的執(zhí)行,直到需要的對象返回為止。
如果在使用 await 導(dǎo)致編譯時錯誤, 確認 await 是否在一個異步函數(shù)中。 例如,在應(yīng)用的 main() 函數(shù)中使用 await , main() 函數(shù)的函數(shù)體必須被標記為 async :
Future main() async {
checkVersion();
print('In main: version is ${await lookUpVersion()}');
}
函數(shù)體被 async 標示符標記的函數(shù),即是一個_異步函數(shù)_。 將 async 關(guān)鍵字添加到函數(shù)使其返回Future。 例如,考慮下面的同步函數(shù),它返回一個 String :
String lookUpVersion() => '1.0.0';
例如,將來的實現(xiàn)將非常耗時,將其更改為異步函數(shù),返回值是 Future 。
Future<String> lookUpVersion() async => '1.0.0';
注意,函數(shù)體不需要使用Future API。 如有必要, Dart 會創(chuàng)建 Future 對象。
如果函數(shù)沒有返回有效值, 需要設(shè)置其返回類型為 Future<void> 。
當需要從 Stream 中獲取數(shù)據(jù)值時, 可以通過一下兩種方式:
提示: 在使用 await for
前,確保代碼清晰, 并且確實希望等待所有流的結(jié)果。 例如,通常不應(yīng)該使用 await for
的UI事件偵聽器, 因為UI框架會發(fā)送無窮無盡的事件流。
一下是異步for循環(huán)的使用形式:
await for (varOrType identifier in expression) {
// Executes each time the stream emits a value.
}
上面 表達式 返回的值必須是 Stream 類型。 執(zhí)行流程如下:
使用 break 或者 return 語句可以停止接收 stream 的數(shù)據(jù), 這樣就跳出了 for 循環(huán), 并且從 stream 上取消注冊。 **如果在實現(xiàn)異步 for 循環(huán)時遇到編譯時錯誤, 請檢查確保 await for 處于異步函數(shù)中。** 例如,要在應(yīng)用程序的 main() 函數(shù)中使用異步 fo r循環(huán), main() 函數(shù)體必須標記為 async` :
Future main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}
有關(guān)異步編程的更多信息,請參考 dart:async 部分。 同時也可參考文章 Dart Language Asynchrony Support: Phase 1 和 Dart Language Asynchrony Support: Phase 2, 以及 Dart language specification 。
更多建議: