Dart异步操作及网络请求

731 阅读2分钟

异步操作

Dart中的异步操作使用Promise来实现,跟js中的Promise很像,直接使用Promise对耗时操作进行包裹即可。

从源码可以看到,Future是一个抽象类,有一个工厂构造方法,如下:

factory Future(FutureOr<T> computation()) {
  _Future<T> result = new _Future<T>();
  Timer.run(() {
    try {
      result._complete(computation());
    } catch (e, s) {
      _completeWithErrorCallback(result, e, s);
    }
  });
  return result;
}

上面源码中,Future接收一个函数:FutureOr<T> computation(),该函数的返回值是:FutureOr<T>,这是联合类型,可以返回Future,也可以返回其他类型。

  1. 简单使用:
main(List<String> args) {
  var ret = getData();
  ret.then((String value){//then方法中处理请求成功的数据
    print(value);
  });
  print("end");
}

//模拟网络请求
Future<String> getData(){
  //将耗时操作使用Future进行包裹
  return Future((){
    sleep(Duration(seconds: 2));
    return "hello world";
  });
}

上面操作中,将模拟的耗时操作使用Future进行包裹,返回“请求到的”数据。在main方法中,使用then来对数据进行处理。跟js中Promise不同,Futrue的构造方法不能接收两个参数来分别对操作成功和操作失败进行处理。js的Promise的使用如下:

function checkCode(code) {
    return new Promise((resolve,reject)=>{//传入两个参数处理不同的情况
        //模拟网络请求,对数字进行验证
        setTimeout(() => {
            if (code==="8888") {//成功,调用resolve
                resolve("success -> " + code);
            }
            else{//失败,调用reject
                reject("bad code! -> " + code);
            }
        }, 2000);
    });
}

那么,Future如何处理操作失败的情况呢?

在Future中,直接通过throw Exception(...)即可。如下:

main(List<String> args) {
  checkCode("8888").then((String value){
    print(value);
  }).catchError((err){//捕捉异常
    print(err);
  });

  checkCode("9999").then((String value){
    print(value);
  }).catchError((err){//捕捉异常
    print(err);
  });
  print("开始校验...");
}

Future<String> checkCode(String code){
  return Future((){
    sleep(Duration(seconds:2));
    if (code=="8888") {
      return "success -> $code";
    }
    else{
      //操作失败,直接抛出异常
      throw Exception("bad code! -> $code");
    }
  });
}
  1. Future.value():将简单的值包裹成Future
    var ret1 = Future((){
      return "hello";
     });
    //等价于
    var ret2 = Future.value("world");
    
  2. Future.error():等价于throw Exception()
  3. Future.delayed(Duration(seconds:3),(){}):延时执行
    Future.delayed(Duration(seconds: 3),(){
      return "delayed ret";
    }).then((value){
      print(value);
    })
    
  4. await/async:已同步方式编写异步代码,跟js的await/async一样。
    • await必须在async函数中使用
    • 如下代码,要求返回的是Future类型,但是实际返回的是String类型,这样也是可以的,因为async修饰的函数内部,会自动将返回值包裹成Future类型。
      Future test() async{
        return "hi";
      }
      

网络请求

在flutter中,常见的网络请求有三种方式:HttpClient、http库、dio库,其中,前两种方式flutter官方提供的。最常用的是dio库。

dio文档