Code前端首页关于Code前端联系我们

在 Flutter 和 Dart 中优雅地使用 async wait

terry 2年前 (2023-09-22) 阅读数 79 #移动小程序

在我们的业务中,存在复杂的异步依赖关系。传统的thenawait async有不同的缺点,就是面对复杂的场景时无法写好代码。本文将帮助您处理 js 的孪生兄弟 dart 中复杂的异步操作。让我们开始吧!

信心十足

以JS多年的经验,秒秒钟写出和JS一样的不是很容易吗?开整

Flutter、Dart中优雅的使用 async await

长得有那么好吗?我们给这两个方法添加一个返回类型,然后再试一次?

Flutter、Dart中优雅的使用 async await

为什么?

Flutter、Dart中优雅的使用 async await

到底是什么?为什么会发生这种情况?不是! ! !

不得不说dart类型系统作弊

我们先看下面的代码。你能猜出下面的输出是什么吗?

Flutter、Dart中优雅的使用 async await

先别急着打开答案。让我们修改代码并将 double 添加到 list2 中。猜猜输出会是什么?

Flutter、Dart中优雅的使用 async await

不知道你猜到了没有,现在我们来揭晓答案

Flutter、Dart中优雅的使用 async await

Flutter、Dart中优雅的使用 async await

这是为什么? ? ?你真的感到很困惑吗? ? ?

Flutter、Dart中优雅的使用 async await

现在请工具人@yaoming来表演

Flutter、Dart中优雅的使用 async await

看到上面的对话,你是否有一个问号?为什么定义 List 不起作用?官方的回答是:作为一种设计,Dart 就是这样设计的。推导和转换后,如果不直接声明public,返回的结果会立即使用推导的类型作为实际类型,并立即成为运行时类型。之前宣布的类型立即就没用了。 。 。我只想问,这是一个陷阱吗?可编译,代码直接OJBK,运行时报错。没有这样的事情。 。 。 ,建议大家仔细阅读上面的对话,以免编译后直接跑到火葬场。 。 。

接下来我们看一下方法定义。它有共同的类型,所以问题很容易解决。catchError中的null]会导致类型不匹配问题

Flutter、Dart中优雅的使用 async await

如果不考虑确切的类型♸,我们改为♸列表。 ,所有代码运行

Flutter、Dart中优雅的使用 async await

但是有一个问题,就是没有提示类型和提示代码。怎么说呢, dart 不支持不同类型的TS,这就不错了。同时也不能像js那样直接解构value。只能使用.first .last获取值。是不是感觉有点麻瓜的感觉?

这个和之前的JS有些区别。 Dart 是强类型语言,不支持像 TS 那样的多种列表类型。这里我们对返回结果有一个清晰的对象关联。我们直接封装对象来包装结果。有什么不对?完全没问题,这里没有 JS 混乱,并且包含了正确的类型。

现在让我们计划一下。此类应包含成功结果、错误和堆栈信息,以及指示是否发生错误的精确值。根据上面的内容,我们可以得到一个这样的类来包装我们,结果看起来还不错不是吗?

class Any<T> {
  final T? ok;
  final dynamic err;
  final dynamic stackTrace;

  bool get hasErr => err != null;

  Any.ok(this.ok, {this.err, this.stackTrace});

  Any.err(this.err, this.stackTrace, {this.ok});

  @override
  String toString() {
    return 'Any{ok: $ok, err: $err, stackTrace: $stackTrace}';
  }
}
复制代码

修改完成代码

import 'dart:async';

Future<void> main() async {
  var a = await any(err());
  print(a);
  print(a.runtimeType);
  print(a.hasErr);
  print(a.ok);
  print(a.ok.runtimeType);
  print(a.err);
  print('==============================');
  var b = await any(succ());
  print(b);
  print(b.runtimeType);
  print(b.hasErr);
  print(b.ok);
  print(b.ok.runtimeType);
  print(b.err);
  print('==============================');
  var c = await any(voidf());
  print(c);
  print(c.runtimeType);
  print(c.hasErr);
  // safe type check. void not any called.
  // print(c.ok);
  // print(c.ok.runtimeType);
  print(c.err);
}

Future<String?> err() async {
  throw Error();
}

Future<String> succ() async {
  return "success";
}

Future<void> voidf() async {
  print('void function.');
}

Future<Any<T?>> any<T>(Future<T> future) {
  return future.then<Any<T?>>((T t) {
    return Any.ok(t);
  }).catchError((err, stackTrace) {
    return Any.err(err, stackTrace, ok: null);
  });
}

class Any<T> {
  final T? ok;
  final dynamic err;
  final dynamic stackTrace;

  bool get hasErr => err != null;

  Any.ok(this.ok, {this.err, this.stackTrace});

  Any.err(this.err, this.stackTrace, {this.ok});

  @override
  String toString() {
    return 'Any{ok: $ok, err: $err, stackTrace: $stackTrace}';
  }
}
复制代码

启动吧

Flutter、Dart中优雅的使用 async await

完美了吗? ? ?以后如果像以前一样遇到复杂的业务场景,我们可以隔离不同的业务,直接做简单的决策,告别N层嵌套

var d1 = await any(doSomething1());
if (d1.hasErr) {
  // do something..
  return;
}
print(d1.ok);
// do something..
var d2 = await any(doSomething2());
if (d2.hasErr) {
  // do something..
  return;
}
print(d2.ok);
// do something..
var d3 = await any(doSomething3());
if (d3.hasErr) {
  // do something..
  return;
}
// more task...
复制代码

总结一下

  • dart也能优雅地工作async和await只能编译完成OJBK
  • 始终注意dart类型系统。代码可以编译并不意味着它可以运行。嘻嘻。毕竟, Promise.any Future.any 这种方式已经存在了。首先,我这里所说的不是两个元素的排列。那么,any这个词更能说明回到这里是对还是错,你必须做出正确的选择

作者:尽管如此,世界依然美丽
链接:https ://juejin.cn/post/7014759220771815431
来源:稀土掘金
版权归作者所有。商业转载请联系作者获取授权。非商业转载请注明出处。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门