Dart 入门(6)异步

7 篇文章 0 订阅
6 篇文章 0 订阅

异步

Future

Dart 里面的异步,和 Java 里面的异步有些区别,要实现异步操作,我们就需要用到 Future 这个关键字,Future 将来的意思,可以放一个泛型 Future<T> ,做为一个返回值,当线程完毕后我们能拿到这个对象,而 Future 对象里面同样有一些静态方法也是可以有异步的效果:

void main() {
  print("start time ${DateTime.now()}");

  Future.delayed(new Duration(seconds:2),(){
      print("delay nowTime = ${DateTime.now()}");
  });
  
  print("end time ${DateTime.now()}");
}

根据代码是按照顺序执行的原理,我们想的打印结果应该为:
1.start time
延迟两秒后打印
2.delay nowTime
3.end time
我们运行起来看看结果:

start time 2021-01-28 15:39:23.941454
end time 2021-01-28 15:39:23.948424
delay nowTime = 2021-01-28 15:39:25.952542

可以看到,delay nowTime 是最后打出来的,说明Future.delayed和他前后两个print并不是同步进行
那么我们要如何才能让他按照我们的预期,同步进行呢?那就是 then方法,修改代码如下:

void main() {
  print("start time ${DateTime.now()}");

  Future.delayed(new Duration(seconds:2),(){
      print("delay nowTime = ${DateTime.now()}");
  }).then((value) => print("end time ${DateTime.now()}"));
  
}

理解一下 then 这个方法,然后的意思,根据意思来看就是延迟两秒后打印时间,然后再打印结束时间,我们运行看看效果:

start time 2021-01-28 15:49:15.639934
delay nowTime = 2021-01-28 15:49:17.652054
end time 2021-01-28 15:49:17.653041

确实,按照我们的预期,打印出了我们想要的结果。
我们在看,delayed,then都有返回结果,那么我们将打印返回,在结束的时候再看看结果如何修改代码如下:

void main() {
  print("start time = ${DateTime.now()}");

  Future.delayed(new Duration(seconds:2),(){
      return "delay nowTime = ${DateTime.now()} ";
  })
  .then((value) => value + " end time = ${DateTime.now()}")
  .then((value) => print(value));
}

我们将打印作为返回值,运行程序,打印结果如下:

start time 2021-01-28 15:55:21.855428
delay nowTime = 2021-01-28 15:55:23.869513  end time 2021-01-28 15:55:23.870512

可以看出,每次的返回值都会成为 then 的参数传入下一个 then
同样我们在这样链式的调用中,也会有异常抛出,那么这样的异常我们应该怎么取捕获呢?Future 给了我们一个静态方法catchError(e),我们修改代码如下:

void main() {
  print("start time = ${DateTime.now()}");

  Future.delayed(new Duration(seconds:2),(){
      return "delay nowTime = ${DateTime.now()} ";
  })
  .then((value) => value + " end time = ${DateTime.now()}")
  .then((value) => throw new Exception(value))
  .catchError((onError){
    print(onError);
  });
}

在最后我们将我们拼接的时间字符串当一个异常抛出去,用我们的catchError(e)去捕获,运行程序如下:

start time = 2021-01-28 16:00:29.391334
Exception: delay nowTime = 2021-01-28 16:00:31.407588  end time = 2021-01-28 16:00:31.408584

可以看到异常被我们捕获了。
好了,现在我们需要做一个网络请求,模拟一个下载操作,我们需要定义自己的异步代码块该怎么做呢?使用 Future 和 async 关键字模拟一个网络下载操作吧。

void main() {
  print("程序开始");
  var downloadUrl = requestDownloadUrl();
  var result = download(downloadUrl);
  print("下载结果:$result");
  print("程序结束");
}

Future<String> requestDownloadUrl() async {// 请求下载地址
  print("开始请求下载地址....");
  return "www.baidu.com";
}

Future<String> download(var downloadUrl) async{// 开始下载文件
  print("开始进行下载操作,下载地址为:$downloadUrl");
  return "下载成功";
}

我们创建了两个方法,一个是请求下载地址,一个开始下载文件,而且开始下载文件这个方法需要请求下载地址成功后的结果,两个都是耗时操作,我们用 Future 和 async 将他们定义为异步方法。然后我们在 main 函数中依次调用,我们想要的结果应该是 “程序开始 -> 开始请求下载地址…
-> 开始进行下载操作,下载地址为:www.baidu.com -> 下载成功 程序结束
” 运行程序打印结果如下:

程序开始
开始请求下载地址....
开始进行下载操作,下载地址为:Instance of 'Future<String>'
下载结果:Instance of 'Future<String>'
程序结束

顺序是我们想要的顺序,但是下载地址和下载结果返回的是 Future 对象,因为是异步,获取真正的结果是在未来的一段时间,所以我们需要使用then方法去获取我们异步方法得到的结果,修改程序如下:

void main() {
  print("程序开始");
  requestDownloadUrl()
  .then((value) => download(value))
  .then((value) => print(value + " 程序结束"));
}

Future<String> requestDownloadUrl() async {
  print("开始请求下载地址....");
  return "www.baidu.com";
}

Future<String> download(var downloadUrl) async{
  print("开始进行下载操作,下载地址为:$downloadUrl");
  return "下载成功";
}

我们将代码进行链式调用,运行,打印结果如下:

程序开始
开始请求下载地址....
开始进行下载操作,下载地址为:www.baidu.com
下载成功 程序结束

和我们预期一致。
网上搜索一下 Dart 的异步在 2.0 以下都是用的是 Future then 的方式,现在都是 2.0 以上了,都开始用 async,await,的方式了。好家伙,学了半天,学了个过时的。

async、await

那就继续吧,翻了翻资料,理解理解,发现async , await 的效果好像跟 then 的效果一样,只是这个方式方便对阅读代码。OK,那么改改上面的代码吧:

void main() async {
  print("程序开始");
  String downloadUrl = await requestDownloadUrl();
  String result = await download(downloadUrl);
  print(result);
  print("程序结束");
}

Future<String> requestDownloadUrl() async {
  print("开始请求下载地址....");
  return "www.baidu.com";
}

Future<String> download(var downloadUrl) async {
  print("开始进行下载操作,下载地址为:$downloadUrl");
  return "下载成功";
}

其实也比较简单,在异步方法前面加个 await 等待异步方法调用完毕,返回结果就行,但是 await 又是和 async 成对使用的,所以需要在 await 使用的方法外加上 async。OK,代码修改完毕运行一下看看打印结果:

程序开始
开始请求下载地址....
开始进行下载操作,下载地址为:www.baidu.com
下载成功
程序结束

妥妥的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值