异步编程
Dart中通过 Future
和 Stream
实现异步,谈论他们之前,先简单了解一下什么叫异步。
Asynchrony, in computer programming, refers to the occurrence of events independent of the main program flow and ways to deal with such events. These may be "outside" events such as the arrival of signals, or actions instigated by a program that take place concurrently with program execution, without the program blocking to wait for results.
-- https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)
异步是独立于“主程序流”的一个流,类似于子线程,可以在不阻塞主线程的情况下,执行并返回结果,比如从数据库读取数据,通过异步的形式,可以在读取数据时执行加载动画,等待读取到数据将其显示到界面上。
Future
Dart 中的 Future
类,搭配 await
, async
关键字可以实现简单的异步。
下面的代码模拟一个获取name值的耗时操作:
//模拟耗时操作,获取到 name 需要 2 秒。
Future<String> getName() {
return Future.delayed(Duration(seconds: 2), () => 'Tom');
}
//获取到 name 后将其显示出来。
void printName() {
var name = getName();
print(name);
}
void main() {
printName();
print('something else');
}
输出结果为:

可以看到,main()
里的两个方法是按代码顺序同步执行的,执行 printName()
方法时,getName()
立即返回了一个Future并被打印,然后才打印 “Tom”。
下面改下代码:
//模拟耗时操作,获取到 name 需要 2 秒。
Future<String> getName() {
return Future.delayed(Duration(seconds: 2), () => 'Tom');
}
//获取到 name 后将其显示出来。
void printName() async{
var name = await getName();
print(name);
}
void main() {
printName();
print('something else');
}
输出结果为:

虽然 printName()
的执行需要两秒,但没有阻塞其他代码的执行,"something else "先被打印,两秒后 "Tom" 被打印出来。
改动的部分是 Lines7 的async
和 Lines8 的await
,async
表示程序需要异步执行,await
表示等待异步代码执行完成。
代码说明:
-
Future.delayed(Duration duration, [FutureOr<T> computation()])
这个方法可以便捷地生成一个Future对象,延迟duration
时间执行computation()
,并返回一个
T
类型的对象。 -
await
等待Future
返回执行完成后结果,代码遇到await
会等待 Future 返回结果,再执行下一句代码。
返回值是Future<T>
的方法,如果不加await
,是立即返回一个Future<T>
对象;加上await
,则待Future
执行完毕后返回T
类型的对象。 -
async
标记一个方法为异步方法,使用到 await 关键字的方法必须加 async,否则会提示 "The await expression can only be used in an async function."
捕获异常
跟同步代码捕获异常的方式一样,使用try-catch,代码如下:
Future<String> getName() {
return Future.delayed(
Duration(seconds: 2), () => throw Exception('Something wrong'));
}
void printName() async {
try {
var name = await getName();
print(name);
} catch (e) {
print(e.toString());
}
}
void main() {
printName();
print('Something else');
}
输出结果:

网友评论