FlutterFlutterFlutter入门

Flutter入门(十)Dart中的异步编程——Future、a

2022-12-24  本文已影响0人  会骑车的iOSer

我们知道dart是一门单线程的语言,那么在遇到网络获取数据,写入数据库,从文件读取数据等操作时,我们怎么来处理呢?

其实dart是支持异步操作的,可以使用Future类和asyncawait关键字

事件循环 event loop

dart中有两种队列

在每一次事件循环中,系统会优先去microtask queue中查询是否有可执行的任务,如果没有,才会处理event queue

并且我们平时执行的任务绝大多数都是在event queue中执行的,Dartevent queue的任务建立提供了一层封装,就是我们经常用到的Future

Future

Future<T> 类,其表示一个 T 类型的异步操作结果。如果异步操作不需要结果,则类型为 Future<void>。也就是说首先Future是个泛型类,可以指定类型。如果没有指定相应类型的话,则Future会在执行动态的推导类型。

asyncawait

默认的Future是异步运行的。如果想要我们的Future同步执行,可以通过async和await关键字:

void main() {
  getData();
  print('做点其他事情');
}

String _data = '0';

getData() async {
  print('开始获取data=$_data');
  //1.后面的操作必须是异步才能使用await修饰
  //2.当前函数也必须是async修饰的函数
  await Future((){
    for (int i = 0; i < 10000000; i++) {
      _data = '网络数据';
    }
  });
  print('结束data=$_data');
}

//打印结果
// flutter: 开始获取data=0
// flutter: 做点其他事情
// flutter: 结束data=网络数据

从打印结果可以看出,Future已经同步执行了。await会等待Future执行结束后,才会继续执行后面的代码。

⚠️注意:async/await都只是一个语法糖,编译器或解释器最终都会将其转化为一个Promise(Future)的调用链

Future简单使用

void main() {
  futureValueDemo();
}

futureValueDemo() async{
  var future = await Future.value(1);
  print('future value = $future');//打印结果1
}
void main() {
  futureDelayedDemo();
  print("futureDelayedDemo()执行之后打印。");
}

futureDelayedDemo() async {
  //延迟执行2s
  Future.delayed(Duration(seconds: 2), () {
    print("Future.delayed 2 seconds.");
  });
}

对于Future来说,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。一个Future只会对应一个结果,要么成功,要么失败。
Future的所有API的返回值仍然是一个Future对象,所以可以很方便的进行链式调用。
Dart提供了下面三个方法用来处理Future的结果。

Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError});
Future<T> catchError(Function onError, {bool test(Object error)});
Future<T> whenComplete(FutureOr action());

1.Future.then()

用来注册一个Future完成时要调用的回调。如果 Future 有多个then,它们也会按照链接的先后顺序同步执行,同时也会共用一个event loop。

futureThenDemo() async {
  Future.value(1).then((value) {
    return Future.value(value+1);
  }).then((value) {
    return Future.value(value+2);
  }).then((value) {
    print(value); //输出4
  });
}
futureThenDemo() async {
  int data = 1;
  Future future = Future((){
    data += 2;
  });

  Future((){
    data += 3;
  });

  //这里在future执行完成后立即会被执行,优先于  Future((){
  //     data += 3;
  //   });
  future.then((value) {
    print('data=$data');//输出3
  });
}

2.Future.catchError()
注册一个回调,来捕捉Future的error:

void testFuture() async {
  new Future.error('Future 发生错误啦!').catchError(print, test: (error) {
    return error is String;
  });
}

then中的回调onError和Future.catchError
Future.catchError回调只处理原始Future抛出的错误,不能处理回调函数抛出的错误,onError只能处理当前Future的错误:

void testFuture() async {
  Future.error('Future 发生错误啦!').then((_) {
    throw 'new error';
  }).catchError((error) {
    print('error: $error');
    throw 'new error2';
  }).then(print, onError:(error) {
    print("handle new error: $error"); //输出handle new error: new error2
  });
}

3.Future.whenComplete()
Future.whenComplete 在Future完成之后总是会调用,不管是错误导致的完成还是正常执行完毕。比如在网络请求前弹出加载对话框,在请求结束后关闭对话框。并且返回一个Future对象:

void testFuture() async {
  var random = new Random();
  Future.delayed(new Duration(seconds: 1), () {
    if (random.nextBool()) {
      return 'Future 正常';
    } else {
      throw 'Future 发生错误啦!';
    }
  }).then(print).catchError(print).whenComplete(() {
    print('Future whenComplete!');
  });
}
//输出
// flutter: Future 正常
// flutter: Future whenComplete!

最后

通过这篇文章我们了解了Dart中的事件循环和event queue和microtask queue之间关系。同时,介绍了一些关于Dart Future的一些基础使用和高级用法,同时穿插了一些使用实例,用来帮助大家更好的来理解Dart中的异步操作。

上一篇 下一篇

猜你喜欢

热点阅读