Dart学习笔记(7): future

Dart代码在单线程中执行

代码在运行线程中阻塞的话,会使程序冻结

Future对象(futures)表示异步操作的结果,进程或者IO会延迟完成

在async函数中使用await来挂起执行,直到future完成为止(或者使用then)

在async函数中使用try-catch来捕获异常(或者使用catchError())

Future 的常用函数


Future.delayed()=>延迟执行一个延时任务。

Future.then()=>任务执行完成会进入这里,能够获得返回的执行结果。

 Future.delayed(Duration(seconds: 2), () {
    return 'hello world';
  }).then((value) => print(value));//输出:hello world

Future.catchError()=>有任务执行失败,可以在这里捕获异常。

 Future.delayed(Duration(seconds: 2), () {
    return (3 ~/ 0);
  }).catchError((e) {
    print("异常信息:${e.toString()}");
  }).then((value) => print(value)); 
//输出结果:异常信息:IntegerDivisionByZeroException

Future.whenComplete()=>当任务停止时,最后会执行这里。

Future.delayed(Duration(seconds: 2), () {
    return "hello world";
  }).then((value) => print(value)).whenComplete(() => print("任务已结束"));
输出打印:
hello world
任务已结束

Future.wait()=>可以等待多个异步任务执行完成后,再调用 then()。Future.wait([])接受一个Future数组参数。含义为当数组中的所有的Future都处理完成后,再对每个Future的结果进行处理。

其结果同样返回一个Future数组。可以通过数组下标访问。

Future.wait([
    //2s后返回
    Future.delayed(Duration(seconds: 2), () {
      return 'Hello';
    }),
    //4s后返回
    Future.delayed(Duration(seconds: 4), () {
      return ' world';
    })
  ]).then((value) {
    print(value[0] + value[1]);//输出打印:Hello world
    print(value[0]);//输出打印:Hello
  });
  • 只有有一个执行失败,就会进入 catchError()
 Future.wait([
    //2s后返回
    Future.delayed(Duration(seconds: 2), () {
      return 'Hello';
    }),
    //4s后返回
    Future.delayed(Duration(seconds: 4), () {
      throw '完了,芭比Q了';
    })
  ]).then((value) {
    print(value[0] + value[1]);
  }).catchError((e) {
    print("异常信息:${e}");
  });
//异常信息:完了,芭比Q了

程序往下走到catchError后面的的方法,输出异常信息,而没有走到then,因为只有程序正常执行才会走到then。注意then 要写在catchError后面。

 onError

其实不止catchError方法可以捕获异常,在then方法中还提供了一个可选参数onError,当发生异常的时候,会走到onError参数所传入的方法

Future.wait([
    //2s后返回
    Future.delayed(Duration(seconds: 2), () {
      return 'Hello';
    }),
    //4s后返回
    Future.delayed(Duration(seconds: 4), () {
      throw '完了,芭比Q了';
    })
  ]).then((value) {
    print(value[0] + value[1]);
  },onError: (e){
    print("then中的onError异常信息:${e.toString()}");
  });
输出打印:hen中的onError异常信息:完了,芭比Q了

若同时设置then方法的onError参数和调用catchError方法,

Future.wait([
    //2s后返回
    Future.delayed(Duration(seconds: 2), () {
      return 'Hello';
    }),
    //4s后返回
    Future.delayed(Duration(seconds: 4), () {
      throw '完了,芭比Q了';
    })
  ]).then((value) {
    print(value[0] + value[1]);
  },onError: (e){
    print("then中的onError异常信息:${e.toString()}");
  }).catchError((e) {
    print("catchError 异常信息:${e}");
  });

输出结果:then中的onError异常信息:完了,芭比Q了

结果:可以看到当同时设置onError和catchError的时候,当发生异常时,程序只会走onError,而不会走到catchError


必须在带有 async 关键字的 异步函数 中使用 await

  1. 在调用异步方法的前面多加了一个await关键字,表示这是异步返回,等该异步任务执行成功了才会执行下一行代码
  2. 异步的任务难免会发生异常,所以建议用try/catch代码块包裹起来,在catch里面处理异常

比如现在有个需求场景是用户先登录,登录成功后会获得用户ID,然后通过用户ID,再去请求用户个人信息,获取到用户个人信息后打印

//用户登录
Future login(String userName, String pwd) async {
  if (userName == "jack" && pwd == "123456") {
    return "token";
  }
  return "false";
}

Future getUserInfo(String id) async {
  //获取用户信息
  return "usrName=jack,age=18,id=$id";
}

Future saveUserInfo(String userInfo) async {
  // 保存用户信息,打印

  print("userInfo:$userInfo");

回调地狱的做法:

login("jack", "123456").then((id) => {
        getUserInfo(id).then((userInfo) => {
          saveUserInfo(userInfo)
          })
      });

上面定义的每一个方法都是异步的,都是返回一个Future,所以还有一种比较优雅的实现方法,就是用Future.then的链式调用,在上一个任务的回调里返回下一个任务的执行结果,也就是返回一个Future,而这个任务的回调可以通过Future.then链式调用的方式拼在上一个then的后面,这就避免了多层的回调,执行代码如下所示

login("jack", "123456").then((id) {
    return getUserInfo(id);
  }).then((userInfo) {
    return saveUserInfo(userInfo);
  }).catchError((e) {
    print(e);
  });

使用async/await消除callback hell

通过Future回调中再返回Future的方式虽然能避免层层嵌套,但是还是有一层回调.

使用async/await消除这种嵌套:

async 位于函数名称后面,函数体前,await用在函数体内,其他方法调用前。

void getUser() async {
  try {
    var id = await login("jack", "123456");
    var userInfo = await getUserInfo(id);
    await saveUserInfo(userInfo);
  } catch (e) {
    print(e);
  }
}

通过async/await将一个异步流用同步的代码表示出来了。

你可能感兴趣的:(Dart语言基础,学习,flutter,前端)