Dart程式碼在一個執行的'執行緒'中執行。Future
物件代表非同步操作的結果:稍後要完成的處理或I/O。要暫停執行直到將來完成,要在非同步函式中使用await
(或使用then()
)。要捕獲錯誤,要在非同步函式中使用try-catch
表示式(或使用catchError()
)。要同時執行程式碼,請建立isolate
。
Futures
future是Future<T>
物件,表示產生型別T結果的非同步操作。如果沒有返回結果,則future的型別為Future <void>
,當呼叫返回future的函式時,會發生兩件事:
- 該函式將要完成的工作排隊並返回未完成的Future物件。
- 稍後,當操作完成時,Future物件將以值或錯誤完成。
編寫依賴於未來的程式碼時,您有兩種選擇:
- 使用
async
和await
。 - 使用
Future
api。
async和await
async
和await
關鍵字是Dart語言非同步支援的一部分。 它們允許編寫看起來像同步程式碼的非同步程式碼,而不使用Future API。 非同步函式是在其正文之前具有async
關鍵字的函式。 await
關鍵字僅適用於非同步函式。
注意:在Dart 1.x中,非同步函式立即暫停執行。 在Dart 2中,非同步函式不是立即掛起,而是同步執行,直到第一個等待或返回。
import 'dart:async';
Future<void> printDailyNewsDigest() async {
var newsDigest = await gatherNewsReports();
print(newsDigest);
}
main() {
printDailyNewsDigest();
printWinningLotteryNumbers();
printWeatherForecast();
printBaseballScore();
}
printWinningLotteryNumbers() {
print('Winning lotto numbers: [23, 63, 87, 26, 2]');
}
printWeatherForecast() {
print("Tomorrow's forecast: 70F, sunny.");
}
printBaseballScore() {
print('Baseball score: Red Sox 10, Yankees 0');
}
const news = '<gathered news goes here>';
const oneSecond = Duration(seconds: 1);
Future<String> gatherNewsReports() =>
Future.delayed(oneSecond, () => news);
複製程式碼
處理錯誤
如果Future-returns
函式因錯誤而完成,您可能希望捕獲該錯誤。 非同步函式可以使用try-catch
處理錯誤:
Future<void> printDailyNewsDigest() async {
try {
var newsDigest = await gatherNewsReports();
print(newsDigest);
} catch (e) {
// Handle error...
}
}
複製程式碼
順序處理
可以使用多個await
表示式來確保每個語句在執行下一個語句之前完成:
main() async {
await expensiveA();
await expensiveB();
doSomethingWith(await expensiveC());
}
複製程式碼
在expensiveA()
完成之前,expensiveB()
函式不會執行,依此類推。
Future API
在Dart 1.9中新增async
和await
之前,必須使用Future API
。 您可能仍會看到舊程式碼中使用的Future API以及需要比async-await提供的功能更多的程式碼。
要使用Future API
編寫非同步程式碼,可以使用then()
方法註冊回撥。 當Future
完成時,此回撥將觸發。
import 'dart:async';
Future<void> printDailyNewsDigest() {
final future = gatherNewsReports();
return future.then(print);
}
main() {
printDailyNewsDigest();
printWinningLotteryNumbers();
printWeatherForecast();
printBaseballScore();
}
printWinningLotteryNumbers() {
print('Winning lotto numbers: [23, 63, 87, 26, 2]');
}
printWeatherForecast() {
print("Tomorrow's forecast: 70F, sunny.");
}
printBaseballScore() {
print('Baseball score: Red Sox 10, Yankees 0');
}
const news = '<gathered news goes here>';
const oneSecond = Duration(seconds: 1);
Future<String> gatherNewsReports() =>
Future.delayed(oneSecond, () => news);
複製程式碼
需要為then()
的回撥提供一個引數,即使Future的型別為Future 。 按照慣例,未使用的引數名為_(下劃線)。
final future = printDailyNewsDigest();
return future.then((_) {
print('All reports printed.');
});
複製程式碼
處理錯誤
使用Future API,您可以使用catchError()
捕獲錯誤:
Future<void> printDailyNewsDigest() =>
gatherNewsReports().then(print).catchError(handleError);
複製程式碼
使用Future.wait()完成多個Future
如果函式的執行順序不重要,可以使用Future.wait()
。當傳遞Future.wait()
一個Futures List時,它會立即返回一個Future
。 在所有給定的Futures
完成之前,Future
不會完成。 然後它以一個List
完成,該List
包含原始列表中每個future的值。
Future.wait([expensiveA(), expensiveB(), expensiveC()])
.then((List responses) => chooseBestResponse(responses, moreInfo))
.catchError(handleError);
複製程式碼
如果任何呼叫的函式因異常而完成,則Future.wait()
返回的Future
也會以異常完成。 使用catchError()
來處理異常。