做者 | 弗拉德
來源 | 弗拉德(公衆號:fulade_me)編程
Dart 代碼庫中有大量返回Future
或Stream
對象的函數,這些函數都是異步的,它們會在耗時操做執行完畢前直接返回而不會等待耗時操做執行完畢。async
和await
關鍵字用於實現異步編程,而且讓你的代碼看起來就像是同步的同樣。網絡
能夠經過下面兩種方式,得到Future
執行完成的結果:異步
async
和await
;Future API
;使用async
和await
的代碼是異步的,可是看起來有點像同步代碼。例如,下面的代碼使用await
等待異步函數的執行結果。async
await lookUpVersion();
必須在帶有async
關鍵字的異步函數中使用 await
:ide
Future checkVersion() async { var version = await lookUpVersion(); // 使用 version 繼續處理邏輯 }
儘管異步函數能夠處理耗時操做,可是它並不會等待這些耗時操做完成,異步函數執行時會在其遇到第一個 await
表達式的時候返回一個Future
對象,而後等待await
表達式執行完畢後繼續執行。異步編程
使用try
、catch
以及finally
來處理使用await
致使的異常:函數
try { version = await lookUpVersion(); } catch (e) { // 沒法找到版本時作出的反應 }
你能夠在異步函數中屢次使用await
關鍵字。例如,下面代碼中等待了三次函數結果:code
var entrypoint = await findEntrypoint(); var exitCode = await runExecutable(entrypoint, args); await flushThenExit(exitCode);
await
表達式的返回值一般是一個Future
對象;
若是不是的話也會自動將其包裹在一個Future
對象裏。Future
對象表明一個"承諾",await
表達式會阻塞直到須要的對象返回。對象
若是在使用await
時致使編譯錯誤,請確保await
在一個異步函數中使用。例如,若是想在main()
函數中使用await
,那麼main()
函數就必須使用async
關鍵字標識。事件
Future main() async { checkVersion(); print('在 Main 函數中執行:版本是 ${await lookUpVersion()}'); }
定義異步函數只需在普通方法上加上async
關鍵字便可。
將關鍵字async
添加到函數並讓其返回一個Future
對象。假設有以下返回String
對象的方法:
String lookUpVersion() => '1.0.0';
將其改成異步函數,返回值是Future
:
Future<String> lookUpVersion() async => '1.0.0';
注意,函數體不須要使用Future API
。若有必要,Dart
會建立Future
對象。
若是函數沒有返回有效值,須要設置其返回類型爲 Future<void>
Stream
也是用於接收異步事件數據,和Future
不一樣的是,它能夠接收多個異步操做的結果(成功或失敗)。 也就是說,在執行異步任務時,能夠經過屢次觸發成功或失敗事件來傳遞結果數據或錯誤異常。Stream
經常使用於會屢次讀取數據的異步任務場景,如網絡內容下載、文件讀寫等。舉個例子:
Stream.fromFutures([ // 1秒後返回結果 Future.delayed(new Duration(seconds: 1), () { return "hello 1"; }), // 拋出一個異常 Future.delayed(new Duration(seconds: 2),(){ throw AssertionError("Error"); }), // 3秒後返回結果 Future.delayed(new Duration(seconds: 3), () { return "hello 3"; }) ]).listen((data){ print(data); }, onError: (e){ print(e.message); },onDone: (){ });
上面的代碼依次會輸出:
hello 1 Error hello 3