Dart语言基础(异步支持)(1小时)
Dart类库有非常多的返回Future
或者Stream
对象的函数。 这些函数被称为异步函数:它们只会在设置好一些耗时操作之后返回,比如像 IO操作,网络操作等。而不是等到这个操作完成。
async
和await
关键词支持了异步编程,允许您写出和同步代码很像的异步代码。
Future
Future与JavaScript中的Promise非常相似,表示一个异步操作的最终完成(或失败)及其结果值的表示。简单来说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。一个Future只会对应一个结果,要么成功,要么失败。
值得注意的时,Future的所有API返回值仍然时一个Future对象,所有非常适用于链式调用
Future 常用API
Future.then
下面示例使用一个2s演示模拟耗时操作,在程序开始运行2s后打印出”hello world!“
main() {
Future.delayed(new Duration(seconds: 2),(){
return "hello world!";
}).then((data){ //.then接收异步结果并打印
print(data);
});
}
Future.catchError
如果异步任务发生错误,可以使用 Future.catchErrror
来捕获异常:
Future.delayed(new Duration(seconds: 2),(){
throw Exception("My Exception");
}).then((data){
//执行成功会走到这里
print("success");
}).catchError((e){
//执行失败会走到这里
print(e);
});
我们在异步任务中抛出了一个异常,then的回调函数将不会被执行,取而代之的是 catchError回调函数将被调用, then方法还有一个可选参数onError,我们也可以它来捕获异常:
Future.delayed(new Duration(seconds: 2),(){
throw Exception("My Exception");
}).then((data){
//执行成功会走到这里
print("success");
}, onError: (e) {
print("onError: $e");
}).catchError((e){
//执行失败会走到这里
print("catchError: $e");
});
输出结果:
onError: Exception: My Exception
可以看出,在同一个Feture上,.onError
优先级高于 .catchError
。
Future.whenComplete
当我们遇到无论异步任务执行成功或失败都需要做一些事的场景,比如在网络请求前弹出加载对话框,在请求结束后关闭对话框。
Future.delayed(new Duration(seconds: 2),(){
throw Exception("My Exception");
//throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print("success");
}).catchError((e){
//执行失败会走到这里
print(e);
}).whenComplete((){
print("Complete");
});
Future.wait
当运行结果依赖于有多个异步任务运行结果,比如我们有一个界面,需要先分别从IO和网络两个接口获取数据,两个接口均获取成功后才能进行UI处理,这个时候我们可以使用Future.wait
来出来,它接受一个Future数组参数,只有数组中所有Future都执行成功后,才会触发then的成功回调,只要有一个Future执行失败,就会触发错误回调。
使用方法如下:
Future.wait([Future1,Future2])
.then((){
//处理成功
}).catchError((e){
//处理失败
});
举个例子:
Future.wait([
// 2秒后返回结果
Future.delayed(new Duration(seconds: 2), () {
return "hello";
}),
// 4秒后返回结果
Future.delayed(new Duration(seconds: 4), () {
return " world";
})
]).then((results){
print(results[0]+results[1]);
}).catchError((e){
print(e);
});
通过上面学习,我们可以大概总结出Future的使用步骤:
- 创建Future对象
- 通过
Future.then
方法监听Future内部执行成功时的结果 - 通过
Future.catchError
监听Future内部失败或者异常时的错误信息 - 通过
Future.whenComplete
监听所有任务完成信息
async/await
Dart中的async/await
和JavaScript中的async/await
功能和用法是一模一样的,如果你已经了解JavaScript中的async/await
的用法,可以直接跳过本节。
- async用来表示函数是异步的,定义的函数会返回一个Future对象,可以使用then方法添加回调函数。
- await 后面是一个Future,表示等待该异步任务完成,异步完成后才会往下走;await必须出现在 async 函数内部
使用async/await的目的是将一个异步流用同步的代码表示出来了。
修改下上面2s后打印 “hello world!” 的例子:
main() {
getPrintData().then((data0)=>print(data0));
}
Future<String> getPrintData() async {
String data = await Future.delayed(new Duration(seconds: 2),(){
return "hello world!";
});
return "要打印的数据: "+ data;
}
async/await
都只是一个语法糖,编译器或解释器最终都会将其转化为一个Future
的调用链。
Stream
Stream
也是用于接收异步事件数据,和Future
不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。
Stream.fromFutures([
// 1秒后返回结果
Future.delayed(new Duration(seconds: 1), () {
return "hello world 1";
}),
// 抛出一个异常
Future.delayed(new Duration(seconds: 2),(){
throw AssertionError("Error");
}),
// 3秒后返回结果
Future.delayed(new Duration(seconds: 3), () {
return "hello world 3";
})
]).listen((data){
print(data);
}, onError: (e){
print(e.message);
},onDone: (){
print("Steam done");
});
输出结果:
hello world 1
Error
hello world 3
Steam done
Dart的异步机制
该部分为进阶部分,可以直接跳过,后续需要在阅读。
不同操作语言处理耗时任务有不同的处理机制:
- 多线程,开启一个新的线程,在新线程中进行异步操作,在通过线程间通信,将数据同主线程共享。Java和C++使用这种方式。
- 单线程+事件循环,JavaScript和Dart就是使用这种方式。
有关Dart异步机制,请参考 Dart异步处理机制
参考
https://book.flutterchina.club/chapter1/dart.html
https://segmentfault.com/a/1190000020398241