天天看點

#yyds幹貨盤點#dart系列之:dart中的異步程式設計

簡介

熟悉javascript的朋友應該知道,在ES6中引入了await和async的文法,可以友善的進行異步程式設計,進而擺脫了回調地獄。dart作為一種新生的語言,沒有理由不繼承這種優秀的品質。很自然的,dart中也有await和async語言,一起來看看吧。

為什麼要用異步程式設計

那麼為什麼要用異步程式設計呢? 隻用同步不能夠解決嗎?

其實大多情況下同步已經夠用了,但是在下面的幾種情況下,同步的場景還是有缺陷的。

  1. 需要花很長時間從網絡上下載下傳資料的情況。
  2. 讀取資料庫的耗時情況。
  3. 從檔案讀取資料的情況。

總結而言,如果某些操作需要花費大量的時間,那麼就可以用到異步程式設計了。

怎麼使用

async是方法的描述符,如果要使用await,則必須配合async一起使用:

Future<void> checkVersion() async {
  var version = await lookUpVersion();
  // Do something with version
}
      
注意,await後面一般接着的是Future對象。

先看一個錯誤使用異步程式設計的例子:

String createOrderMessage() {
  var order = fetchUserOrder();
  return 'Your order is: $order';
}

Future<String> fetchUserOrder() =>
    Future.delayed(
      const Duration(seconds: 2),
      () => 'Order one!',
    );

void main() {
  print(createOrderMessage());
}
      

上面的代碼本意是列印出從資料庫耗時取出的資料,但是結果并不是想象的那樣,其原因就是fetchUserOrder方法是一個異步方法,是以不會立即傳回,進而導緻結果列印失敗。

将上面的代碼用async改寫:

Future<String> createOrderMessage() async {
  var order = await fetchUserOrder();
  return 'Your order is: $order';
}

Future<String> fetchUserOrder() =>
    Future.delayed(
      const Duration(seconds: 2),
      () => 'Large Latte',
    );

Future<void> main() async {
  print('Fetching user order...');
  print(await createOrderMessage());
}
      

Future

上面我們在使用async和await的過程中使用到了Future。在java中Future表示的是線程的執行結果。在dart中Future表示的是一個異步執行的結果。

Future有兩種狀态:uncompleted 或者 completed。

當最開始執行一個異步函數的時候,會傳回一個未完成的Future。這個未完成的Future會等等異步執行的完成或者失敗。

不管異步程式是成功還是失敗,最終都會傳回一個完成狀态。

async傳回的Future可以接泛型,表示的時候傳回的具體類型,比如Future 表示的是傳回一個字元串,而 Future表示不傳回任何值。

下面是兩個不同傳回的例子:

Future<String> fetchUserOrder() {
  return Future.delayed(const Duration(seconds: 2), () => 'Large Latte');
}

Future<void> fetchUserOrder() {
  return Future.delayed(const Duration(seconds: 2), () => print('Large Latte'));
}
      

下面是一個異常的例子:

Future<void> fetchUserOrder() {
  return Future.delayed(const Duration(seconds: 2),
      () => throw Exception('Logout failed: user ID is invalid'));
}
      

異步異常處理

在async的函數中,對await的異步方法中抛出的異常,可以直接是用try catch來進行異常的捕獲:

try {
  print('Awaiting user order...');
  var order = await fetchUserOrder();
} catch (err) {
  print('Caught error: $err');
}
      

在同步函數中調用異步函數

上面介紹的fetchUserOrder()傳回的是一個Future,表示的是一個異步執行的過程。

那麼如果是一個同步的方法,比如main()函數中,如何去調用異步方法,并且得到傳回值呢?

await肯定是不行的,因為await隻能在async的方法中調用。這個時候就可以用到then語句:

fetchUserOrder().then(order=>'do something');
      

then語句會等待異步執行傳回結果,然後對結果進行處理,實際上就等同于javascript中的回調。

總結

以上就是dart中async和await的用法。

本文已收錄于 ​​http://www.flydean.com/12-dart-async/​​