先看一个模拟下载文件的例子:
void main(){
print("main start at ${DateTime.now()}");
download();//调用异步任务下载,但是函数前没有加await关键字,表示当前线程不需要等待(不会阻塞)
print("main end at ${DateTime.now()}");
}
//以下是一个异步任务,在新线程中执行
void download() async {
print("download start at ${DateTime.now()}");
await new Future.delayed(const Duration(seconds: 5)); //模拟下载:让当前线程休眠5秒
print("download end at ${DateTime.now()}");
}
}
运行结果:
main start at 2019-06-02 12:49:20.421
download start at 2019-06-02 12:49:20.422
main end at 2019-06-02 12:49:20.423
download end at 2019-06-02 12:49:25.427
可以看到,调用download函数没加await关键字时,表示不会引起当前线程阻塞。
下面把download()函数前面加上await关键字,其它不变:
void main() async{
print("main start at ${DateTime.now()}");
await download();//等待await操作
print("main end at ${DateTime.now()}");
}
void download() async {
print("download start at ${DateTime.now()}");
await new Future.delayed(const Duration(seconds: 5)); //当前线程休眠5秒
print("download end at ${DateTime.now()}");
}
执行结果:
main start at 2019-06-02 12:53:17.014
download start at 2019-06-02 12:53:17.015
download end at 2019-06-02 12:53:22.021
main end at 2019-06-02 12:53:22.022
可以看到,调用download函数前加了await关键字后,表示会等待download执行完毕,才会继续往下执行。
调用函数前面加上await表示,需要等待await操作(一般是耗时操作)执行完毕,才能顺序执行后面的语句。不加await表示,即使有await操作,也不会阻塞当前线程。
要说明的是,函数体内如果有await语句,那么这个函数声明后面就要加上async关键字修饰,否则编译会不通过。如果函数体内没有await调用语句,函数声明后面加上async也不会报错。
以上是不带返回值的情况,下面看看download函数加上返回值的例子。
download函数修改为:
Future<String> download() async { //声明async的函数,返回类型必须是Future类型。
print("download start at ${DateTime.now()}");
await new Future.delayed(const Duration(seconds: 5)); //当前线程休眠5秒
print("download end at ${DateTime.now()}");
return "Hi,I come from server!";//自动转成Future<Sring>类型
}
先看看调用download()函数时不加await操作是怎样的。
main函数修改成:
void main() async {
print("main start at ${DateTime.now()}");
Future<String> content = download(); //不等待await操作,返回值必须是Future不能是String否则编译报错。
//添加监听回调,相当是给异步操作添加了listener
content.then((string) {
print("result[${DateTime.now()}]: $string"); //异步操作完成时执行
});
print("main end at ${DateTime.now()}");
}
执行结果:
main start at 2019-06-02 13:38:56.385
download start at 2019-06-02 13:38:56.386
main end at 2019-06-02 13:38:56.387
download end at 2019-06-02 13:39:01.389
result[2019-06-02 13:39:01.390]: Hi,I come from server!
下面看看调用download()函数时加了await操作是怎样的。
main()函数修改成:
void main() async {
print("main start at ${DateTime.now()}");
String content = await download(); //等待await操作
//虽然download函数返回一个Future<String>对象,但是因为是加了await,所以不需要再用Future来接收返回值,可以直接使用String类型。
print("result[${DateTime.now()}]: $content");
print("main end at ${DateTime.now()}");
}
执行结果:
main start at 2019-06-02 13:41:15.421
download start at 2019-06-02 13:41:15.421
download end at 2019-06-02 13:41:20.425
result[2019-06-02 13:41:20.425]: Hi,I come from server!
main end at 2019-06-02 13:41:20.426
可以看到,加了await与不加await调用函数时,是有明显不同的。加了await相当于是一个同步任务。不加await调用函数,等于是一个异步任务,需要添加回调函数接收异步任务的结果。