異步支持

2021-09-13 09:49 更新

Dart 庫(kù)中包含許多返回 Future 或 Stream 對(duì)象的函數(shù). 這些函數(shù)在設(shè)置完耗時(shí)任務(wù)(例如 I/O 曹組)后, 就立即返回了,不會(huì)等待耗任務(wù)完成。 使用 async 和 await 關(guān)鍵字實(shí)現(xiàn)異步編程。 可以讓你像編寫同步代碼一樣實(shí)現(xiàn)異步操作。


處理 Future

可以通過(guò)下面兩種方式,獲得 Future 執(zhí)行完成的結(jié)果:

  • 使用 async 和 await.
  • 使用 Future API,具體描述,參考 庫(kù)概覽.

使用 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ù)

函數(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> 。


處理 Stream

當(dāng)需要從 Stream 中獲取數(shù)據(jù)值時(shí), 可以通過(guò)一下兩種方式:

  • 使用 async 和 一個(gè) 異步循環(huán) (await for)。
  • 使用 Stream API, 更多詳情,參考 in the library tour。

提示: 在使用 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í)行流程如下:

  1. 等待,直到流發(fā)出一個(gè)值。
  2. 執(zhí)行 for 循環(huán)體,將變量設(shè)置為該發(fā)出的值
  3. 重復(fù)1和2,直到關(guān)閉流。

使用 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 。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)