Flutter——dart(二) 异步

dart(二) 异步

  • Dart类库有非常多的返回Future或者Stream对象的函数。 这些函数被称为异步函数。
  • async和await关键词支持了异步编程,允许您写出和同步代码很像的异步代码。

1. Future

  • Future表示一个异步操作的最终完成(或失败)及其结果值的表示。
  • 简单来说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。一个Future只会对应一个结果,要么成功,要么失败。
  • Future 的所有API的返回值仍然是一个Future对象,所以可以很方便的进行链式调用。

Future.then

为了方便示例,在本例中我们使用Future.delayed 创建了一个延时任务(实际场景会是一个真正的耗时任务,比如一次网络请求),即2秒后返回结果字符串"hi world!",然后我们在then中接收异步结果并打印结果,代码如下:

    Future.delayed(Duration(seconds: 2),(){
       return "hi world!";
    }).then((data){
       print(data);
    });

Future.catchError

  • 如果异步任务发生错误,我们可以在catchError中捕获错误,我们将上面示例改为:

    Future.delayed(Duration(seconds: 2),(){
       //return "hi world!";
       throw AssertionError("Error");
    }).then((data){
       //执行成功会走到这里
       print("success");
    }).catchError((e){
       //执行失败会走到这里
       print(e);
    });
    
  • 在本示例中,我们在异步任务中抛出了一个异常,then的回调函数将不会被执行,取而代之的是 catchError回调函数将被调用;但是,并不是只有 catchError回调才能捕获错误,then方法还有一个可选参数onError,我们也可以用它来捕获异常:

     Future.delayed(Duration(seconds: 2), () {
         //return "hi world!";
         throw AssertionError("Error");
     }).then((data) {
         print("success");
     }, onError: (e) {
         print(e);
     });
    

Future.whenComplete

  • 有些时候,我们会遇到无论异步任务执行成功或失败都需要做一些事的场景,比如在网络请求前弹出加载对话框,在请求结束后关闭对话框。这种场景,有两种方法,

  • 第一种是分别在then或catch中关闭一下对话框,

  • 第二种就是使用Future的whenComplete回调,我们将上面示例改一下:

     Future.delayed(Duration(seconds: 2),(){
        //return "hi world!";
        throw AssertionError("Error");
     }).then((data){
        //执行成功会走到这里
        print(data);
     }).catchError((e){
        //执行失败会走到这里
        print(e);
     }).whenComplete((){
        //无论成功或失败都会走到这里
     });
    

Future.wait

有些时候,我们需要等待多个异步任务都执行结束后才进行一些操作,比如我们有一个界面,需要先分别从两个网络接口获取数据,获取成功后,我们需要将两个接口数据进行特定的处理后再显示到UI界面上,应该怎么做?
答案是Future.wait,它接受一个Future数组参数,只有数组中所有Future都执行成功后,才会触发then的成功回调,只要有一个Future执行失败,就会触发错误回调。下面,我们通过模拟Future.delayed 来模拟两个数据获取的异步任务,等两个异步任务都执行成功时,将两个异步任务的结果拼接打印出来,代码如下:

Future.wait([
  // 2秒后返回结果
  Future.delayed(Duration(seconds: 2), () {
    return "hello";
  }),
  // 4秒后返回结果
  Future.delayed(Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);
}).catchError((e){
  print(e);
});

执行上面代码,4秒后你会在控制台中看到“hello world”。


2. async/await

Dart中的async/await :异步任务串行化。

  • 问题:回调地狱(Callback Hell)
    如果代码中有大量异步逻辑,并且出现大量异步任务依赖其它异步任务的结果时,必然会出现Future.then回调中套回调情况。
  • 解决问题:消除回调地狱。消除回调地狱主要有两种方式:

一、使用Future消除Callback Hell

Future 的所有API的返回值仍然是一个Future对象,所以可以很方便的进行链式调用” ,如果在then 中返回的是一个Future的话,该future会执行,执行结束后会触发后面的then回调,这样依次向下,就避免了层层嵌套。

 login("alice","******").then((id){
        return getUserInfo(id);
    }).then((userInfo){
        return saveUserInfo(userInfo);
    }).then((e){
       //执行接下来的操作
    }).catchError((e){
      //错误处理
      print(e);
    });

二、使用 async/await 消除 callback hell

通过Future回调中再返回Future的方式虽然能避免层层嵌套,但是还是有一层回调,像写同步代码那样来执行异步任务而不使用回调的方式就要使用async/await了:

    task() async {
       try{
        String id = await login("alice","******");
        String userInfo = await getUserInfo(id);
        await saveUserInfo(userInfo);
        //执行接下来的操作
       } catch(e){
        //错误处理
        print(e);
       }
    }
  • async用来表示函数是异步的,定义的函数会返回一个Future对象,可以使用 then 方法添加回调函数。
  • await 后面是一个Future,表示等待该异步任务完成,异步完成后才会往下走;await必须出现在 async 函数内部。
  • 可以看到,我们通过async/await将一个异步流用同步的代码表示出来了。

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


Stream

Stream 也是用于接收异步事件数据,和 Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等。举个例子:

   Stream.fromFutures([
     // 1秒后返回结果
     Future.delayed(Duration(seconds: 1), () {
       return "hello 1";
     }),
     // 抛出一个异常
     Future.delayed(Duration(seconds: 2),(){
       throw AssertionError("Error");
     }),
     // 3秒后返回结果
     Future.delayed(Duration(seconds: 3), () {
       return "hello 3";
     })
   ]).listen((data){
      print(data);
   }, onError: (e){
      print(e.message);
   },onDone: (){

   });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值