本代碼是學習Future
和async
await
關鍵字編寫異步代碼。使用嵌入式DartPad編輯器,您能夠經過運行示例代碼並完成練習來測試您的知識。 本文主要包含:數據庫
async
await
關鍵字。異步操做使您的程序能夠在等待另外一個操做完成的同時完成工做。如下是一些常見的異步操做:markdown
要在Dart中執行異步操做,可使用Future
類和async
和 await
關鍵字。網絡
如下示例顯示了使用異步函數(fetchUserOrder()
)的錯誤方法。稍後,您將使用async和修復示例await。在運行此示例以前,請嘗試找出問題所在–您認爲輸出將是什麼?異步
// This example shows how *not* to write asynchronous Dart code.
String createOrderMessage() {
var order = fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
// Imagine that this function is more complex and slow.
Future.delayed(
Duration(seconds: 2),
() => 'Large Latte',
);
void main() {
print(createOrderMessage());
//Your order is: Instance of '_Future<String>'
}
複製代碼
這就是示例沒法打印fetchUserOrder()最終產生的值的緣由:async
fetchUserOrder()
是一個異步函數,在延遲後,它提供了一個描述用戶順序的字符串:'Large Latte'
,createOrderMessage()
應調用fetchUserOrder()
並等待其完成。由於createOrderMessage()
它沒有等待fetchUserOrder()
到結束,createOrderMessage(
)沒有獲得字符串值fetchUserOrder()
,最終提供的結果。createOrderMessage()
它表明待完成的工做:未完成的future。createOrderMessage()
沒法獲取描述用戶訂單的值,所以該示例沒法在控制檯上打印「 Large Latte」,而是打印「您的訂單是:'_ Future的實例'」。在接下來的部分中,咱們將瞭解Future以及如何使用Future(使用async和await),以便可以將必要的代碼編寫fetchUserOrder() 爲在控制檯上打印所需的值('Large Latte')。編輯器
Fulure表示異步操做的結果,而且能夠具備兩種狀態:未完成或已完成函數
當您調用異步函數時,它將返回一個未完成的Fulure。Fulure正在等待函數的異步操做完成或引起錯誤。oop
若是異步操做成功,則Fulure將以一個值完成。不然,它會以錯誤完成。學習
Future是一個Future<T>
因此,咱們能夠將任何值做爲返回類型測試
若是該函數執行的異步操做因爲任何緣由而失敗,則未來會出現錯誤。
Future<void> fetchUserOrder() {
// Imagine that this function is fetching user info from another service or database.
return Future.delayed(Duration(seconds: 2), () => print('Large Latte'));
}
void main() {
fetchUserOrder();
print('Fetching user order...');
//Fetching user order...
//Large Latte
}
複製代碼
在如下示例中,fetchUserOrder()
返回打印到控制檯後完成的Fulure。由於它不返回可用的值,因此 fetchUserOrder()
的類型Future<void>
。在運行示例以前,請嘗試預測將首先打印的內容:「'Large Latte'
」或「Fetching user order...
」。
運行如下示例以查看未來如何完成並出現錯誤。稍後,您將學習如何處理該錯誤。
Future<void> fetchUserOrder() {
// Imagine that this function is fetching user info but encounters a bug
return Future.delayed(Duration(seconds: 2),
() => throw Exception('Logout failed: user ID is invalid'));
}
void main() {
fetchUserOrder();
print('Fetching user order...');
//Fetching user order...
//Uncaught Error: Exception: Logout failed: user ID is invalid
}
複製代碼
在此示例中,fetchUserOrder()
顯示一個錯誤,指示用戶ID無效。
這個錯誤的演示是爲了理解學習如何使用async和await關鍵字得到結果
Future<T>
實例產生類型的值T
若是Future未產生可用價值,則Future的類型爲 Future<void>
。
Future可能處於如下兩種狀態之一:未完成或已完成。
當您調用返回將來的函數時,該函數會將要完成的工做排隊,並返回未完成的將來。
當future的操做完成時,future以一個值或一個錯誤完成。
在async和await關鍵字提供一個聲明的方式來定義異步函數,並使用其結果。使用async和時請記住如下兩個基本準則await:
main()
從同步功能轉換爲異步功能的示例。
void main() async { ··· }
複製代碼
若是函數具備聲明的返回類型,則將類型更新爲 Future<T>
,其中T是函數返回的值的類型。若是該函數未明確返回值,則返回類型爲 Future<void>
:
Future<void> main() async { ··· }
如今您有了async函數,可使用await關鍵字等待未來完成:
print(await createOrderMessage());
如如下兩個示例所示,asyncand await關鍵字生成的異步代碼看起來與同步代碼很是類似。異步示例中突出顯示了惟一的區別,
String createOrderMessage() {
var order = fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
// Imagine that this function is
// more complex and slow.
Future.delayed(
Duration(seconds: 2),
() => 'Large Latte',
);
void main() {
print('Fetching user order...');
print(createOrderMessage());
// Fetching user order...
// Your order is: Instance of _Future<String>
}
複製代碼
Future<String> createOrderMessage() async {
var order = await fetchUserOrder();
return 'Your order is: $order';
// Fetching user order...
// Your order is: Large Latte
}
Future<String> fetchUserOrder() =>
// Imagine that this function is
// more complex and slow.
Future.delayed(
Duration(seconds: 2),
() => 'Large Latte',
);
Future<void> main() async {
print('Fetching user order...');
print(await createOrderMessage());
}
複製代碼
異步示例在三種方面有所不一樣:
createOrderMessage()
從變化String到Future<String>
。createOrderMessage()
和main()
。fetchUserOrder()
和createOrderMessage()
。一個async函數同步運行直到第一個 await關鍵字。這意味着在async函數體內,第一個await關鍵字以前的全部同步代碼將當即執行。
Future<void> printOrderMessage() async {
print('Awaiting user order...');
var order = await fetchUserOrder();
print('Your order is: $order');
}
Future<String> fetchUserOrder() {
// Imagine that this function is more complex and slow.
return Future.delayed(Duration(seconds: 4), () => 'Large Latte');
}
Future<void> main() async {
countSeconds(4);
await printOrderMessage();
}
// You can ignore this function - it's here to visualize delay time in this example.
void countSeconds(int s) {
for (var i = 1; i <= s; i++) {
Future.delayed(Duration(seconds: i), () => print(i));
}
}
複製代碼