前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >打赌你不知道的两个await使用细节

打赌你不知道的两个await使用细节

作者头像
睡觉谁叫
发布2022-12-22 08:49:31
3120
发布2022-12-22 08:49:31
举报
文章被收录于专栏:Flutter性能监控Flutter性能监控

一. 多个异步使用效率问题

Future.wait处理多个不相关异步任务同时分发的场景可以提高程序执行效率,最终总耗时是其中耗时最长任务耗时,不是所有任务总和。

1. 常规写法

await是Dart语言提供的语法糖,因其可读性和易用性很容易存在乱用而影响代码效率的情况。如下callFuns中模拟了两个异步任务fun1耗时2s, fun2耗时3s,

代码语言:javascript
复制
main(List<String> args) async {
  var t1 = DateTime.now().millisecondsSinceEpoch;
  await callFuns();
  var t2 = DateTime.now().millisecondsSinceEpoch;
  print('cost ${t2 - t1}');
}

Future callFuns() async {
  var r = await fun1();
  var r2 = await fun2();
  print('r = $r');
  print('r2 = $r2');
}

Future<String> fun1() {
  return Future.delayed(Duration(seconds: 2), () {
    return "future 1";
  });
}

Future<String> fun2() {
  return Future.delayed(Duration(seconds: 3), () {
    return "future 2";
  });
}

输出结果:

Untitled.png
Untitled.png

看起来没啥问题~~~ ,但是其实可以用Future.wait来提高程序运行效率。

2. Future.wait写法

代码语言:javascript
复制
main(List<String> args) async {
  var t1 = DateTime.now().millisecondsSinceEpoch;
  await callFuns2();
  var t2 = DateTime.now().millisecondsSinceEpoch;
  print('cost ${t2 - t1}');
}

Future callFuns2() async {
  var rArr = await Future.wait([fun1(), fun2()]);
  var r = rArr[0];
  var r2 = rArr[1];
  print('r = $r');
  print('r2 = $r2');
}

Future<String> fun1() {
  return Future.delayed(Duration(seconds: 2), () {
    return "future 1";
  });
}

Future<String> fun2() {
  return Future.delayed(Duration(seconds: 3), () {
    return "future 2";
  });
}

输出结果:

Untitled 1.png
Untitled 1.png

3. 多个await都可以转换成Future.wait提高运行效率么?

答案是否定的! 这涉及到await语法糖解决的是什么问题和应用场景,await解决的是相互依赖的Future间回调地狱和代码可读性问题,如下代码:

代码语言:javascript
复制
login("alice","******").then((id){
 //登录成功后通过,id获取用户信息
 getUserInfo(id).then((userInfo){
    //获取用户信息后保存
    saveUserInfo(userInfo).then((){
       //保存用户信息,接下来执行其他操作
        ...
    });
  });
})

可以看到获取用户信息和保存用户信息这两个Future之间是有依赖关系的,后者依赖前者的结果userInfo。

所以如果有多个不相关的异步可以用Future.wait来处理,因为wait参数中多个任务之间并没有必然的依赖关系,但是如果直接有依赖关系,则不适用Future.wait的场景。

二. 循环中执行异步任务

不要在Iterable的foreach方法执行await异步任务,它们不是顺序执行的。

1. 常规写法

代码语言:javascript
复制
void main(){

  f() async{
    [1,2,3].forEach((i) async {
      String r = await getNetworkData(i);
      print('r= $r');
    });

    print('done');
  }

  f();
}

Future<String> getNetworkData(int second) {
  return Future.delayed(Duration(seconds: 3), () {
    return "network data $second";
  });
}

猜猜上面执行结果是怎样的? 没错,不是你想的那样:顺序打印数据最后打印done ,而是

Untitled 2.png
Untitled 2.png

2. 正确的写法

用for in 或者 Future.foreach

代码语言:javascript
复制
void main() {
  f2() async {
    for (final i in [1, 2, 3]) {
      String r = await getNetworkData(i);
      print('r= $r');
    }

    print('done');
  }

  f3() {
    Future.forEach<int>([1, 2, 3], (i) async {
      String r = await getNetworkData(i);
      print('r= $r');
    }).then((value) {
      print('done');
      ;
    });
  }

  //f2和f3均可
  //f2();
  f3();
}

Future<String> getNetworkData(int second) {
  return Future.delayed(Duration(seconds: 3), () {
    return "network data $second";
  });
}

输出:

Untitled 3.png
Untitled 3.png

三. 参考链接

【Flutter 异步编程 -伍】 | 深入剖析 Future 类源码实现 - 掘金

异步编程: 一次性搞懂 Promise, async, await (#js #javascript)_哔哩哔哩_bilibili

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-12-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 多个异步使用效率问题
    • 1. 常规写法
      • 2. Future.wait写法
        • 3. 多个await都可以转换成Future.wait提高运行效率么?
        • 二. 循环中执行异步任务
          • 1. 常规写法
            • 2. 正确的写法
            • 三. 参考链接
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档