Dart2基礎--異步支持

Dart庫中包含許多返回 FutureStream 對象的函數。這些函數是異步的:它們在啓動一個耗時操作(例如I/O操作)後返回,而不是等待該耗時操作完成。

asyncawait 關鍵字支持異步編程,它們使你編寫異步代碼看起來跟編寫同步代碼一樣。

處理Futures

當你需要一個已經完成了的Future對象的結果時,你有兩個選擇:

使用asyncawait 的代碼是異步的,但是看起來像是同步代碼。例如,這裏的代碼使用 await 來等待一個異步函數的結果:

await lookUpVersion();

要使用 await ,代碼必須在一個異步函數內部—一個被標記爲 async 的函數:

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

注意: 雖然異步函數可能執行耗時的操作,但它不會等待這些操作。相反,異步函數只在遇到第一個await表達式時執行( details )。然後它會返回一個Future對象,盡在 await 表達式完成之後才恢復執行。

在使用 await 的代碼處通過 trycatchfinally 來處理錯誤以及清理工作。

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

你可以在一個異步函數裏多多次使用 await 。例如:

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

await 表達式中,表達式的值通常是一個 Future ;如果不是,那麼他的值會被自動的封裝爲一個 Future 對象。這個 Future 對象會保證返回一個對象。 await 表達式的值就是那個返回的對象。 await 表達式使得執行暫停,直到結果對象可用。

如果你在使用 await 時出現一個編譯時錯誤,確保 await 是在一個異步函數中。例如,要在你的APP的 main() 函數中使用 await ,那麼 main() 函數的函數體必須被標記爲 async

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

聲明異步函數

一個異步函數是一個函數體被標記爲 async 的函數。
給一個函數添加 async 關鍵字使它返回一個 Future 。例如,考慮下面這個返回一個字符串的同步函數:

String lookUpVersion() => '1.0.0';

如果你將它改變成異步函數,那麼它的返回值是一個 Future。

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

注意,函數的函數體不需要使用 Future API .Dart 會在需要的時候創建 Future 對象。
如果你的函數不需要返回一個有用的值,那麼它的返回類型是 Future<void>

處理流(Streams)

當你需要從一個流(Stream)獲取值時,你有兩個選擇:

  • 使用 async 和一個異步 for 循環( await for
  • 使用 Stream API,in the library tour

一個異步 for 循環的格式如下:

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 for 在一個異步函數中。例如,在你的APP的 main() 函數中使用一個異步 for 循環, main() 的函數體必須被標記爲 async

Future main() async {
  // ...
  await for (var request in requestServer) {
    handleRequest(request);
  }
  // ...
}

關於異步編程的更多信息,請參考:dart:async.

生成器(Generators)

當你需要延遲產生一些數據序列時,使用生成器函數。Dart 支持兩種生成器函數:

  • 同步生成器:返回一個Iterable 對象
  • 異步生成器:返回一個Stream 對象

要實現一個 同步 生成器函數,將函數體標記爲 sync* ,並且使用yield 語句來發送數據。

Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}

要實現一個 異步 生成器函數,將函數體標記爲 async* ,並且使用 yield 語句來發送數據。

Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}

如果你的生成器是遞歸的,你可以使用 yield* 來提升它的性能:

Iterable<int> naturalsDownFrom(int n) sync* {
  if (n > 0) {
    yield n;
    yield* naturalsDownFrom(n - 1);
  }
}

可調用的類

要允許像函數一樣調用Dart類的實例,實現 call() 方法即可:

class WannabeFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

main() {
  var wf = new WannabeFunction();
  var out = wf("Hi","there,","gang");
  print('$out');
}

Isolates

大多數計算機,即使是在移動平臺上,都擁有多核心CPU。要充分使用所有的這些核心,開發人員傳統上使用共享內存的線程併發執行。然而,共享狀態的併發執行容易出錯,並且可能導致代碼複雜化。

所有Dart代碼都在 isolates 中運行,而不是線程。每一個 Isolate 都有它自己的內存堆,這就確保沒有任何 Isolate 狀態可以被其他任意 isolate 訪問。

關於 Isolates 的更多信息, dart:isolate library documentation

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章