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