Flutter - Dart : wait a forEach ends

后端 未结 3 1957

I try to modify a string using data in each node I retrieve from Firebase database, and then to write a file with the modifed string (called \"content\").

He

相关标签:
3条回答
  • 2021-01-06 18:07

    If you use for(... in ) instead of forEach you can use async/await

    Future someMethod() async {
      ...
    
      for(final jsonString in response.value) {
         ...
         // cacheManager.getFile returns a Future<File>
         cacheManager.getFile(signedurl).then((file){ 
             // Modify content
             content=content.replaceAll('test',file.path);
         });
      });
    }
    

    With forEach the calls fire away for each jsonString immediately and inside it await works, but forEach has return type void and that can't be awaited, only a Future can.

    0 讨论(0)
  • 2021-01-06 18:19

    You defined the callback for forEach as async, which means that it runs asynchronously. In other words: the code inside of that callback runs independently of the code outside of the callback. That is exactly why print("test"); runs before the code inside of the callback.

    The simplest solution is to move all code that needs information from within the callback into the callback. But there might also be a way to await all of the asynchronous callbacks, similar to how you already await the once call above it.

    Update I got working what I think you want to do. With this JSON:

    {
      "data" : {
        "key1" : {
          "created" : "20181221T072221",
          "name" : "I am key1"
        },
        "key2" : {
          "created" : "20181221T072258",
          "name" : "I am key 2"
        },
        "key3" : {
          "created" : "20181221T072310",
          "name" : "I am key 3"
        }
      },
      "index" : {
        "key1" : true,
        "key3" : true
      }
    }
    

    I can read the index, and then join the data with:

    final ref = FirebaseDatabase.instance.reference().child("/53886373");
    final index = await ref.child("index").once();
    List<Future<DataSnapshot>> futures = [];
    index.value.entries.forEach((json) async {
      print(json);
      futures.add(ref.child("data").child(json.key).once());
    });
    Future.wait(futures).then((List<DataSnapshot> responses) {
      responses.forEach((snapshot) {
        print(snapshot.value["name"]);
      });
    });
    
    0 讨论(0)
  • 2021-01-06 18:24

    Have you tried:

    File file = await cacheManager.getFile(signedurl);
    content = content.replaceAll('test', file.path);
    

    instead of:

    cacheManager.getFile(signedurl).then((file){ ...});
    

    EDIT:

    Here's a fuller example trying to replicate what you have. I use a for loop instead of the forEach() method:

    void main () async {
      List<String> str = await getFuture();
      print(str);
      var foo;
    
      for (var s in str) {
        var b = await Future(() => s);
        foo = b;
      }
    
      print('finish $foo');
    }
    
    getFuture() => Future(() => ['1', '2']); 
    
    0 讨论(0)
提交回复
热议问题