# [異步編程](https://dart.dev/libraries/async/async-await)
相關主題
* [Streams](https://hackmd.io/@asdf121472/S12kHzZr1l)
* [Concurrency](https://dart.dev/language/concurrency)
* [Asynchrony support](https://dart.dev/language/async)
* [videos](https://youtube.com/playlist?list=PLjxrf2q8roU0Net_g1NT5_vOO3s_FR02J&si=whZ5pcHq60gQNta1)
* [Future class](https://api.dart.dev/dart-async/Future-class.html)
* [Stream class](https://api.dart.dev/dart-async/Stream-class.html)
* [Futures and error handling](https://dart.dev/libraries/async/futures-error-handling)
* [dart:async](https://dart.dev/libraries/dart-async)
## 重要觀念
### Future物件代表尚未執行完成的事件
```
Future<String> fetchUserOrder() {
return Future.delayed(Duration(seconds: 1), () => 'Large Latte');
}
```
上列程式的回傳類型是 Future<回傳值類型>, 被呼叫時會立刻回傳`Instance of 'Future<String>'`給呼叫者, 直到 `Future.delayed`執行完成, 才會回傳真正的結果String: `'Large Latte'`, 所以以下程式列印不出 "Large Latte"
```
String createOrderMessage() {
var order = fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
// Imagine that this function is more complex and slow.
Future.delayed(
const Duration(seconds: 2),
() => 'Large Latte',
);
void main() {
print(createOrderMessage());
//print: Your order is: Instance of 'Future<String>'
}
```
### async, async*, await
**async**: 標示函數為異步函數(單一回傳值)
**async***: 標示函數為異步Generator函數(多個回傳值)
**Stream**: 異步Generator函數的返回值不只一個, 會儲存在Stream<回傳值類型> 中
```
// Stream像是有多個值的可迭代物件
Stream<int> countStream(int max) async* {
for (int i = 1; i <= max; i++) {
// generator用 yield 返回值
yield i;
}
}
```
**await**: 用 ansyc, ansyc* 修飾的異步函數內部才能使用 await. await expression 會阻塞, 等待expression執行結束, 才繼續執行.
**同步操作**:同步操作會阻止其他操作執行,直到完成為止。
**同步函數**:同步函數僅執行同步操作。
**異步操作**:異步操作一旦啟動,就允許其他操作在完成之前執行。
**異步函數**:異步函數至少執行一項異步操作,也可以執行同步操作。
### What is a future?
(以下以future 代表一個Future類的實例)
Future 表示異步操作的結果,可以有3種狀態:未完成 或 已完成with value, 已完成with Error.
呼叫異步函數時,它會 **立刻** 回傳一個未完成的 future。該 future 正在等待函數異步操作完成或拋出錯誤。如果異步操作成功,future 將完成並附帶一個值。否則,它將完成並出現錯誤。
`Future<String>` 代表 future完成時會回傳一個String.`Future<void>` 代表完成時沒有回傳值.如果執行的異步操作因任何原因失敗,則回傳一個Error。
### Execution within async functions
```
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(const Duration(seconds: 4), () => 'Large Latte');
}
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) {
/* i=1 到 s的 futures 會立刻同時啟動,
每個future會執行完自己的延遲時間後
才print(i)
所以總共只延遲 s 秒
*/
for (var i = 1; i <= s; i++) {
Future.delayed(Duration(seconds: i), () => print(i));
}
}
/* print:
Awaiting user order...
1
2
3
4
Your order is: Large Latte
*/
```
### [try-on-catch-finally](https://hackmd.io/@asdf121472/BJIOCHI1kl)
異步編程和一般編程相同, 可以用try-catch作錯誤處理
```
Future<void> printOrderMessage() async {
try {
print('Awaiting user order...');
var order = await fetchUserOrder();
print(order);
} catch (err) {
print('Caught error: $err');
}
}
Future<String> fetchUserOrder() {
// Imagine that this function is more complex.
var str = Future.delayed(
const Duration(seconds: 4),
() => throw 'Cannot locate user order');
return str;
}
void main() async {
await printOrderMessage();
}
// print:
// Awaiting user order...
// Caught error: Cannot locate user order
```