「这是我参与11月更文应战的第20天,活动概略检查:2021最后一次更文应战」

今天这篇文章我们来介绍一下Dart中的异步编程;

我们先来看一段代码:

String _string = '默许';
void main() {
  getData();
  print('其他业务');
}
getData() {
  print('初步');
  for (int i = 0; i < 10000000000; i++) {
    _string = '耗时操作';
  }
  print('结束:$_string');
}

其实行打印效果如下:

Flutter(二十二)-Dart中的异步编程Future

在这段代码中,for循环的耗时操作卡着了后续代码的实行;

那么怎么想for循环变成异步操作呢?这个时分我们需求用到Future;

Future

FutureJavaScript中的Promise非常类似,标明一个异步操作的毕竟结束及其效果的标明。简略来说Future便是用来处理异步操作的,异步处理成功了就实行成功的操作,异步处理失利了就捕获差错或许间断后续操作。一个Future只会对应一个效果,要么成功,要么失利;

需求留心的是,Future的全部API的回来值依然是一个Future方针,所以我们可以很方便的进行链式调用;

我们将代码批改如下:

String _string = '默许';
void main() {
  getData();
  print('其他业务');
}
getData() {
  print('初步:$_string');
  Future(() {
    for (int i = 0; i < 10000000000; i++) {
      _string = '耗时操作';
    }
    print('结束:$_string');
  });
}

工作效果:

Flutter(二十二)-Dart中的异步编程Future

经过工作效果我们发现,将for循环放进Future中之后,耗时操作将不会堵塞代码的实行;

await/async

Flutter中还有一种方法可以让我们像写同步代码一样来实行异步任务而不用运用回调的方法,这便是async/await了,我们来看一段代码:

String _string = '默许';
void main() {
  getData();
  print('其他业务');
}
getData() async {
  print('初步:$_string');
  await Future(() {
    for (int i = 0; i < 1000000000; i++) {
      _string = '网络数据';
    }
    print('获取到数据:$_string');
  });
  print('结束:$_string');
}

在此段代码中getData方法运用了async标识,而在方法内部for循环地点的Future添加了await标识,那么会有什么效果呢?

Flutter(二十二)-Dart中的异步编程Future

可以看到,Future之外的代码,比及Future中代码实行结束之后才持续实行了;

那么,syncawait都是什么效果呢?

  • async用来标明函数是异步的,定义的函数会回来一个Future方针,可以运用then方法添加回调函数
  • await后边是一个Future,标明等候该异步任务结束,异步结束后才会持续往下实行;await必须出现在async函数内部;

可以看到,我们经过运用asyncawait将一个异步流调用运用同步的代码逻辑标明了出来;

asyncawait仅仅一个语法糖,编译器或许解说器毕竟都会将其转化为一个Future的调用链;

then

那么,假如不运用await,我们能否结束相同的效果呢?

Future方法的回来值依然是一个Future方针,我们运用Future方针接纳此回来值;然后经过future.then来打印一下回来的数据: 我们将getData方法批改如下:

getData() async {
  print('初步:$_string');
  Future future = Future(() {
    for (int i = 0; i < 1000000000; i++) {
      _string = '网络数据';
    }
    print('获取到数据:$_string');
  });
  future.then((value) {
    print('then方法: $_string');
  });
  print('结束:$_string');
}

我们看一下打印效果:

Flutter(二十二)-Dart中的异步编程Future

我们可以看到,尽管没有了await标识,可是Future方针的then方法中依然可以获取到异步任务的数据;

可是此刻then方法中的value却是空的:

Flutter(二十二)-Dart中的异步编程Future

这是因为,Future中捕获的异步任务没有回来值,那么我们给这个异步任务添加一个回来值,我们将getData方法批改如下:

getData() async {
  print('初步:$_string');
  Future future = Future(() {
    for (int i = 0; i < 1000000000; i++) {
      _string = '网络数据';
    }
    print('获取到数据:$_string');
    return '回来数据';
  });
  future.then((value) {
    print('then方法: $_string, value: $value');
  });
  print('结束:$_string');
}

我们再来看一下打印效果:

Flutter(二十二)-Dart中的异步编程Future

此刻,then方法中回来的value已经有值了,值为异步任务中return的回来值;在Future中回来的数据会被包装进Future的方针中,然后回来一个Future的方针;

catchError

许多情况下,我们在进行网络处理的时分的时分,会抛出失常,那么在Future中应该怎么处理失常呢?

我们来看下边代码:

getData() async {
  print('初步:$_string');
  Future future = Future(() {
    for (int i = 0; i < 1000000000; i++) {
      _string = '网络数据';
    }
    throw Exception('网络失常');
  });
  future.then((value) {
    print('then方法: $_string, value: $value');
  });
  print('结束:$_string');
}

Future内部,经过throw抛出了一个Exception,我们来看一下代码的实行效果:

Flutter(二十二)-Dart中的异步编程Future

可以看到,实行过程中代码报错,抛出了网络失常的差错信息;那么我们就需求进行阻拦,将Exception捕获到,不能在实行中让工程犯错,这个时分我们就需求运用catchError捕获失常,我们将代码批改如下:

Flutter(二十二)-Dart中的异步编程Future

工作效果:

Flutter(二十二)-Dart中的异步编程Future

我们确实捕获到了失常,可是工程依然报错了,这是为什么呢?这个时分,我们需求用到链式调用,在then方法之后,直接运用链式调用来捕获失常,代码如下:

Flutter(二十二)-Dart中的异步编程Future

工作效果:

Flutter(二十二)-Dart中的异步编程Future

onError

then的定义如下:

Future<R> then<R>(FutureOr<R> onValue(T value), {Function? onError});

我们发现,在then方法中还有一个onError方法,此方法也可以用来处理差错以及失常:

Flutter(二十二)-Dart中的异步编程Future

工作效果:

Flutter(二十二)-Dart中的异步编程Future

可以看到,运用then中的onError方法捕获差错之后,catchError将不会调用;

此处的onError方法是在then内部定义的,所以需求在then方法内部调用,而非平级;

catchError是在整个Future的链式调用过程中捕获失常,而onError只在当时then中处理;我们在一个链式调用的过程中可能存在多个then

我们将catchErrorthen方法交换次序:

Flutter(二十二)-Dart中的异步编程Future

工作效果:

Flutter(二十二)-Dart中的异步编程Future

我们发现,假如catchErrorthen方法前面,即使在catchError中捕获了失常,那么then方法依然会实行;

whenComplete

有时分,我们的异步任务不论成功与失利,都需求去做一些其他工作的时分,有两种方法处理*

  • then或许catchError中处理;
  • 运用FuturewhenComplete回调处理;

我们将代码批改如下:

Flutter(二十二)-Dart中的异步编程Future

工作效果:

Flutter(二十二)-Dart中的异步编程Future

尽管我们的whenComplete结束情况实行了,可是失常依然被抛出了;这里有两种方法处理:

  • whenComplete运用链式调用方法,不运用Future的方针调用;
  • whenComplete之后,再次捕获失常,代码如下:

Flutter(二十二)-Dart中的异步编程Future

我们一般运用过程中将then方法中放在前面,这样当失常捕获时,then方法将不会实行:

Flutter(二十二)-Dart中的异步编程Future

在项目中运用时,我们举荐以下写法:

Flutter(二十二)-Dart中的异步编程Future

举荐将各个情况的逻辑处理方法抽出,如下:

Flutter(二十二)-Dart中的异步编程Future