Dart代码在一个执行的'线程'中运行。Future对象代表异步操作的结果:稍后要完成的处理或I/O。要暂停执行直到将来完成,要在异步函数中使用await(或使用then())。要捕获错误,要在异步函数中使用try-catch表达式(或使用catchError())。要同时运行代码,请创建isolate。
Futures
future是Future<T>对象,表示产生类型T结果的异步操作。如果没有返回结果,则future的类型为Future <void>,当调用返回future的函数时,会发生两件事:
- 该函数将要完成的工作排队并返回未完成的Future对象。
- 稍后,当操作完成时,Future对象将以值或错误完成。
编写依赖于未来的代码时,您有两种选择:
- 使用
async和await。 - 使用
Futureapi。
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()来处理异常。