前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dart | 你知道 sync*/async* 是怎么用的吗?

Dart | 你知道 sync*/async* 是怎么用的吗?

作者头像
Flutter笔记
发布2019-08-23 16:21:28
2.2K0
发布2019-08-23 16:21:28
举报
文章被收录于专栏:Flutter笔记

平时我们在写业务逻辑的时候,肯定都会与网络打交道,那肯定也就避免不了异步请求,代码类似如下:

代码语言:javascript
复制
int getData() async {
  Response r = await Dio().get('https://www.baidu.com');
  return r.data;
}

这段代码相信很多人都非常非常熟悉了,我们也都知道 async 是什么意思,那加上一个星号,你还知道吗?

加上星号其实就是「函数生成器」的意思。

那我们先从「sync/sync*」说起。

sync/sync*

「sync」我们都知道是默认程序运行的状态,举个例子:

代码语言:javascript
复制
foo1 (){
  print('foo1 start');
  for(int i = 0; i < 3; i++){
    print(i);
  }
  print('foo1 stop');
}

当我们在 main函数里运行,结果大家应该都很清楚:

foo1 start 0 1 2 foo1 stop

那所谓的函数生成器呢?

被「sync*」标记的函数,一定要返回一个 「Iterable」,这样的函数生成器叫做同步生成器:

代码语言:javascript
复制
Iterable<int> foo2() sync*{
  print('foo2 start');
  for(int i = 0; i < 3; i++){
    print('运行了foo2,当前index:${i}');
    yield i;
  }
  print('foo2 stop');
}

这回我们在 main 函数里运行 foo2(),会出现什么效果?

答案是什么也不会发生,print也没有打印。

这是为什么?

当我们调用 foo2()的时候,这里会马上返回一个 Iterable,就像网络请求会马上返回一个 Feature一样。

但是在我们没有调用 IterablemoveNext 的时候,当前函数体是不会执行的。

而当我们调用了 moveNext 方法后,代码会执行到 yield 关键字的位置,并且在这里停住。

当我们再一次调用 moveNext 后,会再恢复执行,然后再次停到 yield 关键字的位置,依次循环,当没有下一个值得时候,函数会隐式的调用 return方法来终止函数。

来看一下调用方式和结果:

代码语言:javascript
复制
var b = foo2().iterator;
print('还没开始调用 moveNext');
b.moveNext();
print('第${b.current}次moveNext');
b.moveNext();
print('第${b.current}次moveNext');
b.moveNext();
print('第${b.current}次moveNext');

结果为:

代码语言:javascript
复制
还没开始调用 moveNext
foo2 start
运行了foo2,当前index:0
第0次moveNext
运行了foo2,当前index:1
第1次moveNext
运行了foo2,当前index:2
第2次moveNext

从运行结果上来看,我们的说法是正确的,下面就来说一下异步生成器。

async/async*

说异步生成器之前,先来说一下普通的异步调用。

现在有一个这样的需求,我想每隔一秒钟请求一下数据,一共请求10次,看看有没有人关注我等等,

如果使用原始的 async,该怎么做?

代码语言:javascript
复制
getData() async {
  for (int i = 0; i < 10; i++){
    await Future.delayed(Duration(seconds: 1), ()async {
        Data data = await getXXX();
      setState(){
        //业务逻辑
      };
    });
  }
}

这里使用循环,然后每一秒钟请求依次接口,返回数据后 setState();

这样肯定不行,因为你不可能一两秒钟就 setState()一次,

这个时候 async* 就派上用场了:

代码语言:javascript
复制
Stream<Data> getData() async* {
  for (int i = 0; i < 10; i++){
    await Future.delayed(Duration(seconds: 1));
    yield await getXXX();
  }
}

在页面上,我们可以用 StreamBuilder 来包住,这样每次返回数据就不用 setState() 了。

总结

其实函数生成器可能一年都用不上一两次,但是当你用到之后,就会觉得真的很舒服。

其实我个人认为这种函数生成器还有一种作用就是可以让一个函数返回多个值

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • sync/sync*
  • async/async*
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档