前言
因为在Dart语言中是单线程模型,所以不能像java那样利用多线程的特性开一个子线程,在子线程中来进行耗时操作。因此,我们需要用异步的方式来进行耗时操作,如网络请求、数据库操作、文件读写等。
例子
首先,在pubspec.yaml文件中加入依赖
dependencies:
http: ^0.13.5
然后,新建一个dart文件来尝试怎么运用异步操作,我们定义了一个私有方法startMethod(),并标记为async,表明这是一个异步方法,在这个方法里打印3条语句,嵌套了一个getHttp()方法。
getHttp()方法也是一个异步方法,并且进行了耗时操作(网络请求),返回一个字符串。这时可能大家就有疑惑,为啥方法返回值是Future,但我返回字符串也可以呢?别着急,接着往下看。
import 'package:http/http.dart' as http;
main(){
_startMethod();
print("C start");
}
Future _startMethod() async{
print('A start');
print(await getHttp());
print('A end');
}
Future getHttp() async{
final result = await http.get(Uri.https('jianshu.com'));
return 'result :${result.headers}';
}
运行main方法,得到的返回值如下:
A start
C start
result :{...}
A end
程序按顺序运行,第一行打印没有什么问题,但是为啥第二行直接打印的是C start呢,这就是Dart语言中异步方法的作用了。
在async方法中,在遇到await之前的语句都正常执行,遇到await之后的方法都进行等待,并执行await后面的代码(请求http),等到结果返回才继续执行下面的代码。
且遇到await时该方法(_startMethod)会立即返回一个Future,不影响上层调用的执行(打印 C start)
tips
在这里其实省略了一个Future的用法,Future其实后面会跟一个泛型,代表这个函数未来会返回一个什么类型的结果
未省略版:
import 'package:http/http.dart' as http;
main(){
_startMethod();
print("C start");
}
Future<void> _startMethod() async{
print('A start');
print(await getHttp());
print('A end');
}
Future<String> getHttp() async{
final result = await http.get(Uri.https('jianshu.com'));
return 'result :${result.headers}';
}
语法
Working with futures: async and await
The
async
andawait
keywords provide a declarative way to define asynchronous functions and use their results. Remember these two basic guidelines when usingasync
andawait
:
- To define an async function, add
async
before the function body:- The
await
keyword works only inasync
functions.
在定义异步函数时,async必须在函数体之前
await 关键字必须在 异步函数中才有用
进阶
接下来,我们在getHttp()方法中加入两行打印,再来查看运行结果
import 'package:http/http.dart' as http;
main(){
_startMethod();
print("C start");
}
Future _startMethod() async{
print('A start');
print(await getHttp());
print('A end');
}
Future getHttp() async{
print('B http start');
final result = await http.get(Uri.https('jianshu.com'));
print('B http end');
return 'result :${result.headers}';
}
结果如下:
A start
B http start
C start
B http end
result :{...}
A end
刚开始看到这个结果,可能会有点转不过来。这里其实是一种递归的思想,我们按照规则一步步走就很好理解了。
程序按顺序执行,首先打印 A start 然后,执行print(await getHttp()),_startMethod方法开始等待。
然后打印 b http start ,继续执行http.get方法,getHttp开始等待。因为没有执行完http.get,所以向_startMethod返回一个Future。同理,print(await getHttp())没有执行完,_startMethod返回一个Future,main方法同步执行C start。
当http.get执行完毕后,继续执行 B http end,打印 result, A end。