Flutter异步(二)

flutter中的异步(二)

什么是Future对象

Future是一种对异步任务的结果的封装,也可以理解为是对暂时未完成的任务的一种预期。

Future是可以指定泛型的,下面的例子就是Future返回了一个File类型的结果。

js 复制代码
void saveToFile(TaskResult result) {
  String filePath = path.join(Directory.current.path, "out.json");
  File file = File(filePath);
  String content = json.encode(result);
  Future<File> futureFile = file.writeAsString(content);
}

Future对象在任务开始时就已经生成了,但是在诞生的时候Future对象并不知道最终会生成什么样的结果,因此Future对象需要监听任务回调的结果,dart中提供了两个工具来完成这一任务分别是thencatchError,这两个工具分别用来监听成功完成和异常结束的场景。

Future对任务回调的监听

js 复制代码
void saveToFile(TaskResult result) {
  String filePath = path.join(Directory.current.path, "out.json");
  File file = File(filePath);
  String content = json.encode(result);
  Future<File> futureFile = file.writeAsString(content);
  futureFile.then((File file) { // tag1
    print('写入成功:${file.path}');
  });
}

Future#then方法用来监听文件写入的结果。

js 复制代码
void saveToErrorFile(TaskResult result) {
  String filePath = path.join(Directory.current.path, "error","out.json");
  File file = File(filePath);
  String content = json.encode(result);
  Future<File> futureFile = file.writeAsString(content);
  
  // 监听任务成功完成
  futureFile.then((File file) {
    print('写入成功:${file.path}');
  });
  
  // 监听任务异常结束
  futureFile.catchError((err) { 
    print("catchError:$err");
  });
}

catchError方法用来监听任务是否写入异常,并对异常结果进行自定义操作。

有的时候我们既需要监听任务完成时的结果,又需要监听异常同时还要保证任务不会被终止,这时候可以使用whenComplete方法(这个方法有点像java中的finally,即不管代码是否出现异常都会完成接下去的操作)

FutureOr对象

FutureOr是一个比较特别的对象,它是一个私有构造的抽象类,并不可以被实例化,并且他代表Future和类型,这是一个一类两型的特殊存在(即File和Future都可以被看做是FutureOr对象)

catchError方法的返回值

js 复制代码
futureFile = futureFile.catchError((err){
  print("catchError::[${err.runtimeType}]::$err");
  return File('this is error file');
});

futureFile.then((value){
  print(value.path);
});

当发生异常时会打印"This is error file",当不发生异常时会正常输出

异步成功回调

then方法的返回值

异步成功回调一般使用then去监听回调结果,then方法的定义如下:

js 复制代码
    Future<R> then<R>(FutureOr<R> onValue(T value), {Function? onError});

第一个入参是函数对象,其中函数参数是 T 类中值,也就是 Future 的泛型类型;该函数还有一个返回值,类型为 FutureOr<R> 。其中 R 泛型是方法指定的泛型,then 方法的返回值是 R 泛型的 Future 对象。 以下为具体使用实例:

js 复制代码
Future<String> thenResult = futureFile.then<String>((File file) {
  print('写入成功:${file.path}');
  return file.readAsString();
});

thenResult.then((String value){
  print('读取成功:${value}');
});

then方法中的onError

then方法有两个入参,第一个是必传的回调函数,此外还有一个onError的可选回调,需要注意的是一旦在then中提供onError回调后,对then的返回值再监听catchError将会无效。

async/await关键字的使用

当有多个异步任务需要按顺序执行的时候then就会显得有些臃肿,为了解决这个问题引入async/await这个关键字组合,await关键字只能在async修饰的方法中引用,且用await修饰的Future对象,必须等待上个异步对象完成后,才可以执行下一行代码。

js 复制代码
void readFile(TaskResult result) async{
  String filePath = path.join(Directory.current.path,"config","config.json");
  File configFile = File(filePath);
  String configContent = await configFile.readAsString(); // tag1
  String assetsPath = json.decode(configContent)['assets_file_path'];
  
  File assetsFile = File(assetsPath);
  String assetsContent = await assetsFile.readAsString();
  print(assetsContent);
  dynamic map = json.decode(assetsContent);
  int count = map['read_count'];
  map['read_count'] = count+1;
  
  File resultFile = await assetsFile.writeAsString(json.encode(map));
  print("写入成功:${resultFile.path}");
}

但是需要注意的是,await修饰的异步任务结束后才会继续向下执行,因此只有之后的逻辑和任务结果相关时,才有使用的价值,如果两个异步任务没有任何关系,当使用await修饰第一个异步任务时,第二个异步任务必须等到第一个完成才可以开始执行,这是完全没有必要的,反而会起到阻塞的反效果。

相关推荐
余生H15 分钟前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍18 分钟前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
axihaihai23 分钟前
网站开发的发展(后端路由/前后端分离/前端路由)
前端
流烟默35 分钟前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch
2401_857297911 小时前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
茶卡盐佑星_1 小时前
meta标签作用/SEO优化
前端·javascript·html
Ink1 小时前
从底层看 path.resolve 实现
前端·node.js
金灰1 小时前
HTML5--裸体回顾
java·开发语言·前端·javascript·html·html5
茶卡盐佑星_1 小时前
说说你对es6中promise的理解?
前端·ecmascript·es6
Promise5201 小时前
总结汇总小工具
前端·javascript