認識 Dart 非同步操作

前言

在 Dart 中,使用 Future 表示一個非同步的操作,和 JavaScript 的 Promise 非常相似。

概念

  • Dart 程式碼運行在單執行緒中。
  • 阻塞執行序的程式碼會使程式凍結。
  • 一個 Future 物件(futures)用於表示非同步操作的結果,處理中的操作或 I/O 會在之後完成。
  • 可以在非同步函式中使用 await 關鍵字阻塞程式碼的執行,直到對應的 future 完成。
  • 可以使用 try-catch 陳述式捕獲非同步函式中程式碼的執行錯誤。

使用

Future 裡,使用 return 表示完成(resolve),使用 throw 拋出錯誤(reject)。

1
2
3
4
5
6
7
8
9
Future<String> usesAwait(Future<String> later) async {
return await later;
}

Future<void> asyncError() async {
throw 'Error!';
}

Future<void> asyncValue() async => 'value';

或使用 Completer 物件,操作一個可以決定完成(resolve)或拋出錯誤(reject)時機的 Future

1
2
3
4
5
6
7
8
9
10
11
Future<String> calculate() async {
var completer = new Completer<String>();
Timer(Duration(seconds: 1), () {
if (1 + 1 == 3) {
completer.complete('ok');
} else {
completer.completeError('error');
}
});
return completer.future;
}

範例

新增一個 main.dart 檔。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import 'dart:async';

void main() async {
try {
print(await delay(3));
print(await delayWithError(3));
} catch (e) {
print(e);
}
}

Future<String> delay(int seconds) async {
return Future.delayed(Duration(seconds: seconds), () {
return 'done';
});
}

Future<String> delayWithError(int seconds) async {
var completer = new Completer<String>();
Timer(Duration(seconds: seconds), () {
completer.completeError('error');
});
return completer.future;
}

執行。

1
dart main.dart

結果:

1
2
3
4
# after 3 seconds
done
# after 3 seconds
error

程式碼

參考資料