简体   繁体   English

Dart/Flutter - 回调函数中的“yield”

[英]Dart/Flutter - "yield" inside a callback function

I need to yield a list for a function;我需要为一个函数生成一个列表; however, I want to yield the list from within a callback function, which itself is inside the main function - this results in the yield statement not executing for the main function, but rather for the callback function.但是,我想从回调函数中生成列表,该回调函数本身位于主函数内部 - 这导致 yield 语句不是为主函数执行,而是为回调函数执行。

My problem is very similar to the problem that was solved here: Dart Component: How to return result of asynchronous callback?我的问题与这里解决的问题非常相似: Dart Component: How to return result of asynchronous callback? but I cannot use a Completer because I need to yield and not return.但我不能使用 Completer,因为我需要让步而不是返回。

The code below should describe the problem better:下面的代码应该更好地描述问题:

Stream<List<EventModel>> fetchEvents() async* { //function [1]
    Firestore.instance
        .collection('events')
        .getDocuments()
        .asStream()
        .listen((snapshot) async* { //function [2]
      List<EventModel> list = List();
      snapshot.documents.forEach((document) {
        list.add(EventModel.fromJson(document.data));
      });

      yield list; //This is where my problem lies - I need to yield for function [1] not [2]
    });
  }

Instead of .listen which handles events inside another function you can use await for to handle events inside the outer function.而不是.listen处理另一个函数内的事件,您可以使用await for来处理外部函数内的事件。

Separately - you might want to reconsider the pattern when you yield List instances that are still getting populated inside an inner stream callback...另外-当您产生仍在内部流回调中填充的List实例时,您可能需要重新考虑该模式...

Stream<List<EventModel>> fetchEvents() async* {
  final snapshots =
      Firestore.instance.collection('events').getDocuments().asStream();
  await for (final snapshot in snapshots) {
    // The `await .toList()` ensures the full list is ready
    // before yielding on the Stream
    final events = await snapshot.documents
        .map((document) => EventModel.fromJson(document.data))
        .toList();
    yield events;
  }
}

I would like to add a suggestion for improvement here.我想在这里添加一个改进建议。 The suggested await for solution should be avoided in some cases as it is non dismissible listener and it newer stops listening so this might lead to memory leaks.在某些情况下应该避免建议的await for解决方案,因为它是不可关闭的侦听器,并且它更新停止侦听,因此这可能导致内存泄漏。 You could as well use .map to transform the stream yield results like so (havent tried to compile it, but main idea should be clear):您也可以使用.map像这样转换流产生结果(没有尝试编译它,但主要思想应该很清楚):

Stream<List<EventModel>> fetchEvents() { // remove the async*
    Firestore.instance
        .collection('events')
        .getDocuments()
        .asStream()
        .map((snapshot) { // use map instead of listen
      List<EventModel> list = List();
      snapshot.documents.forEach((document) {
        list.add(EventModel.fromJson(document.data));
      });

      return list; // use return instead of yield
    });
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM