一、Dart 异步编程基础
Dart 是一门单线程的语言,它通过异步操作来执行耗时任务,从而可以在等待一个操作完成的同时进行别的操作。常见的异步操作包括通过网络获取数据、写入数据库、从文件读取数据等。要在Dart
中执行异步操作,可以使用Future
类和async
和await
关键字。
二、Future 类
在 Dart 中,执行异步操作的核心是 Future
类。Future<T>
表示一个 T
类型的异步操作结果。如果异步操作不需要结果,则类型为 Future<void>
。
Future 工厂构造函数:Future
的工厂构造函数接收一个 Dart 函数作为参数,这个函数没有参数,返回值是 FutureOr<T>
类型。可以根据返回的Future进行后续操作。
void main() {
Future((){
print("future run");
});
print("future test start");
}
//打印输出
//future test start
//future run
三、async和await关键字的运用
-
async关键字:标记一个函数为异步函数,使其返回一个
Future
对象。 -
await关键字:用于等待一个
Future
完成。它只能出现在异步函数内部,可以暂停当前函数的执行,直到Future
完成,但不会阻塞事件循环,能够让我们可以像写同步代码那样来执行异步任务而不使用回调的方式。 -
async/await的实质:它们是Dart语言异步支持的语法糖,最终会被转化为
Future
的调用链。
main() async{
void runFuture() async {
var result =await Future.value(1);
print("futrure result $result");
}
runFuture();
print("runFuture()执行之后打印。");
}
//打印结果为:
//runFuture()执行之后打印。
//futrure result 1
四、事件队列与微任务队列的机制
在Dart
中,实际上有两种队列:
-
事件队列(Event Queue):包含所有外来事件,如I/O操作、鼠标事件、绘制事件等。
正常情况下,声明一个
Future
时,Dart
会将异步任务的函数执行体放入event queue
,然后继续同步执行后续的代码。当同步执行的代码执行完毕后,event loop
会按照加入event queue
的顺序(即声明顺序),依次取出事件,最后同步执行Future
的函数体及后续的操作。 微任务队列(Microtask Queue):优先级高于事件队列,用于存放短时间内会完成的异步任务。主要由Dart内部产生。
可以使用scheduleMicrotask
或者Future.microtask
来创建一个微任务去执行。
如果Future
已经执行完毕了,再来获取到这个Future
的引用,然后再继续调用then()
方法。那么此时,Dart
会将后续加入的then()
方法体放入microtask queue
,尽快执行。
在每次事件循环中,Dart会先处理微任务队列中的任务,然后再处理事件队列中的任务。如果微任务队列中有太多任务,可能会阻塞事件队列中的任务,导致触摸、绘制等外部事件卡顿。
五、Future的处理方式
Future.value()
创建一个返回指定value
值的Future
Future.delayed()
创建一个延迟执行的Future
。传参接受一个Duration对象,传入延时时间;再传入方法体执行延时后的操作。
void delayFuture() async {
Future.delayed(Duration(milliseconds: 3000), () {
print("delayed Future");
});
}
Future结果的处理方式
Future.then()
用于注册一个Future
完成时要调用的回调,可以链式调用处理多个异步操作的结果。
void testFuture() async {
Future.value(1).then((value) {
return Future.value(value + 2);
}).then((value) {
return Future.value(value + 3);
}).then(print);
}
Future异常的处理方式
Future.catchError:注册一个回调,来捕捉Future
的error
then
中的回调onError
Future.catchError
回调只处理原始Future
抛出的错误
onError只能处理当前Future的错误
Future.error('Future 发生错误啦!').then((_) {
throw 'new error';
}).catchError((error) {
print('error: $error');
throw 'new error2';
}).then(print, onError:(error) {
print("handle new error: $error");
});
Future.whenComplete():无论Future
成功还是失败,都会执行的回调,用于执行一些清理工作或日志记录等。
FUture.timeout:为Future设置超时时间,超出时间后Future会抛出
TimeoutException`
void testFuture() async {
new Future.delayed(new Duration(seconds: 2), () {
return 1;
}).timeout(new Duration(seconds:1)).then(print).catchError(print);
}