首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Flutter】Future, async, await

【Flutter】Future, async, await

作者头像
老孟Flutter
发布2021-07-15 15:59:54
发布2021-07-15 15:59:54
1.4K00
代码可运行
举报
文章被收录于专栏:FlutterFlutter
运行总次数:0
代码可运行

Dart 为单线程语言,但它提供了异步编程的方式,Future, async, await 为异步编程的类和关键字,

Future

Future.then

异步编程最常用的场景是访问网络接口,返回数据,这里我们模拟这样的场景,2秒后返回网络数据,代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
Future<String> getMyName() {
  Future.delayed(Duration(seconds: 2), () => '老孟');
}

下面将获取到的数据打印出来,

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() {
  var name = getMyName();
  print('name:$name');
}

上面的用法是典型的错误用法,而且也是大部分初学者容易犯错的地方,getMyName 为 Future 方法,表示此方法为异步方法。

上面的代码打印日志如下:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: name:Instance of 'Future<String>'

正确的用法如下:

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() {
  getMyName().then((String value) {
    print('name:$value');
  });
}

2秒后打印日志:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: name:老孟
Future.then.catchError

有这样一个Future方法:延迟1秒将字符串转换为int类型,代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
Future<int> parse(String value) {
  return Future.delayed(Duration(seconds: 1), () {
    return int.parse(value);
  });
}

调用此方法:

代码语言:javascript
代码运行次数:0
运行
复制
parse("2").then((int value) {
  print('value:$value');
});

此时可以正确转换,输出日志:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: value:2

如果入参为非数字,则会出现转换异常,代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
parse("2a").then((int value) {
  print('value:$value');
});

运行,抛出异常:

此时,需要捕获异常并做处理,代码如下:

代码语言:javascript
代码运行次数:0
运行
复制
parse("2a").then((int value) {
  print('value:$value');
}).catchError((error){
  print('error:$error');
});

输出日志:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: error:FormatException: Invalid radix-10 number (at character 1)
2a
^

Future 的异常不能使用 try..catch 捕获。

Future 可以返回任意类型的值,也可以不返回值,

代码语言:javascript
代码运行次数:0
运行
复制
Future<void> futureVoid() {
  return Future.delayed(Duration(seconds: 1), () {
    //do something
  });
}
Future.delayed

延迟处理,上面已经多次使用,延迟1秒执行:

代码语言:javascript
代码运行次数:0
运行
复制
Future.delayed(Duration(seconds: 1), () {
  //do something
});
Future.value

创建一个带返回值的 Future

代码语言:javascript
代码运行次数:0
运行
复制
Future<String> futureValue() {
  return Future.value('老孟');
}
Future.any

返回[futures]中要完成的第一个Future的结果,返回的第一个结果表示已完成,其他Future结果被抛弃。如果[futures]为空,或者没有一个Future完成,那么Future永远不会完成。

代码语言:javascript
代码运行次数:0
运行
复制
Future<String> futureAny() {
  return Future.any([
    Future.delayed(Duration(seconds: 1),()=> '1'),
    Future.delayed(Duration(seconds: 2),()=> '2'),
    Future.delayed(Duration(seconds: 3),()=> '3'),
  ]);
}

输出日志:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: value:1
Future.microtask

Flutter 的 main isolate 中有2个队列:Event Queue 和 Microtask Queue ,这两个 Queue 区别是 Microtask Queue执行的优先级比Event Queue高。

Future.microtask 是向Microtask Queue添加任务,而其他Future 方法是向Event Queue中添加任务。

代码语言:javascript
代码运行次数:0
运行
复制
Future<String> futureMicrotask() {
  return Future.microtask(()=>'老孟');
}
Future.sync

表示Future中代码是同步执行的。

代码语言:javascript
代码运行次数:0
运行
复制
Future<void> futureSync() {
  return Future.sync(()=>print('Future.sync'));
}

调用:

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() {
  print('Future.sync begin');
  futureSync();
  print('Future.sync end');
}

打印日志:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: Future.sync begin
flutter: Future.sync
flutter: Future.sync end
Future.error

返回异常,可以通过catchError捕获。

代码语言:javascript
代码运行次数:0
运行
复制
Future<void> futureSync() {
  return Future.sync(() => print('Future.sync'));
}

调用:

代码语言:javascript
代码运行次数:0
运行
复制
futureError().catchError((error) {
  print('$error');
});

输出日志:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: this is error
Future.doWhile

重复执行操作,直到返回 false。

代码语言:javascript
代码运行次数:0
运行
复制
Future<void> futureDoWhile() {
  var i = 0;
  return Future.doWhile(() {
    print('i:$i');
    return Future.value(i++ < 10);
  });
}

日志输出:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: i:0
flutter: i:1
flutter: i:2
flutter: i:3
flutter: i:4
flutter: i:5
flutter: i:6
flutter: i:7
flutter: i:8
flutter: i:9
flutter: i:10
Future.forEach

遍历完所有的值或者抛出异常才变为完成状态。

代码语言:javascript
代码运行次数:0
运行
复制
Future<void> futureForEach() {
  return Future.forEach([1,2,3,5],(value){
    print('value:$value');
  });
}

日志输出:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: value:1
flutter: value:2
flutter: value:3
flutter: value:5

async, await

async 和 await 关键字允许我们像写同步代码一样写异步代码,有如下异步函数:

代码语言:javascript
代码运行次数:0
运行
复制
Future<int> parse(String value) {
  return Future.delayed(Duration(seconds: 1), () {
    return int.parse(value);
  });
}

可以使用如下方法获取结果:

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() {
  parse('2').then((value) => print('value:$value'));
}

也可以使用如下方法:

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() async {
  var result = await parse('2');
  print('result:$result');
}

日志输出:

代码语言:javascript
代码运行次数:0
运行
复制
flutter: result:2

使用async 和 await 可读性更强。

使用 async 修饰的方法返回 Future,是异步方法。

代码语言:javascript
代码运行次数:0
运行
复制
Future<int> toInt(String value) async {
  return int.parse(value);
}

async 和 await 的异常捕获需要使用try..catcch

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() async {
  try{
    await parse('1');
  }catch(e){
    
  }
}

总结

async 和 await 关键字可以认为是 Future 的语法糖。

async 和 await 关键字可以有效的解决 Future.then 嵌套问题

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() {
  fun1().then((value) {
    fun2().then((value) {
      fun3().then((value) {});
    });
  });
}

Future<String> fun1() {
  return Future.value('a');
}

Future<String> fun2() {
  return Future.value('b');
}

Future<String> fun3() {
  return Future.value('c');
}

这种地狱嵌套可读性非常差,使用async 和 await 写法:

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() async {
  var result1 = await fun1();
  var result2 = await fun2();
  var result3 = await fun3();
}

Future.then 可以使用链式调用

代码语言:javascript
代码运行次数:0
运行
复制
void _incrementCounter() async {
  fun1()
      .then((value) {})
      .then((value){});
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老孟Flutter 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Future
    • Future.then
      • Future.then.catchError
      • Future.delayed
      • Future.value
      • Future.any
      • Future.microtask
      • Future.sync
      • Future.error
      • Future.doWhile
      • Future.forEach
  • async, await
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档