簡介
熟悉javascript的朋友應該知道,在ES6中引入了await和async的語法,可以方便的進行非同步程式設計,從而擺脫了回撥地獄。dart作為一種新生的語言,沒有理由不繼承這種優秀的品質。很自然的,dart中也有await和async語言,一起來看看吧。
為什麼要用非同步程式設計
那麼為什麼要用非同步程式設計呢? 只用同步不能夠解決嗎?
其實大多情況下同步已經夠用了,但是在下面的幾種情況下,同步的場景還是有缺陷的。
- 需要花很長時間從網路上下載資料的情況。
- 讀取資料庫的耗時情況。
- 從檔案讀取資料的情況。
總結而言,如果某些操作需要花費大量的時間,那麼就可以用到非同步程式設計了。
怎麼使用
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<String> 表示的是返回一個字串,而 Future<void>表示不返回任何值。
下面是兩個不同返回的例子:
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<String>,表示的是一個非同步執行的過程。
那麼如果是一個同步的方法,比如main()函式中,如何去呼叫非同步方法,並且得到返回值呢?
await肯定是不行的,因為await只能在async的方法中呼叫。這個時候就可以用到then語句:
fetchUserOrder().then(order=>'do something');
then語句會等待非同步執行返回結果,然後對結果進行處理,實際上就等同於javascript中的回撥。
總結
以上就是dart中async和await的用法。
本文已收錄於 http://www.flydean.com/12-dart-async/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!