Флаттер - Дарт: подождите, пока не закончится - PullRequest
0 голосов
/ 21 декабря 2018

Я пытаюсь изменить строку, используя данные в каждом узле, который я извлекаю из базы данных Firebase, а затем записать файл с измененной строкой (называемой «содержимым»).

Вот что япопробовал:

// Retrieve initial content from Firebase storage
var data = await FirebaseStorage.instance.ref().child("...").getData(1048576);
var content = new String.fromCharCodes(data);

// Edit content with each node from Firebase database
final response = await FirebaseDatabase.instance.reference().child('...').once();
response.value.forEach((jsonString) async {
     ...
     // cacheManager.getFile returns a Future<File>
     cacheManager.getFile(signedurl).then((file){ 
         // Modify content
         content=content.replaceAll('test',file.path);
     });
});

// Finally write the file with content
print("test");
final localfile = File('index.html');
await localfile.writeAsString(content);

Результат:

"тест" отображается до окончания forEach.

Я обнаружил, что мы можем сделатьв дротике (https://groups.google.com/a/dartlang.org/forum/#!topic/misc/GHm2cKUxUDU):

ждут Future.forEach

, но в моем случае, если я это сделаю: ожидайте Future.response.value.forEach (звукинемного странно)

тогда я получаю:

Получатель не найден: 'response'. await Future.response.value.forEach ((jsonString) async {

Как дождаться окончания forEach (с измененным «содержимым»), прежде чем записывать файл с новым содержимым?

Есть идеи?

Ответы [ 3 ]

0 голосов
/ 21 декабря 2018

Вы пробовали:

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

вместо:

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

РЕДАКТИРОВАТЬ:

Вот более полный пример, пытаясь повторить то, чтоу тебя есть.Я использую цикл for вместо метода forEach():

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 голосов
/ 21 декабря 2018

Если вы используете for(... in ) вместо forEach, вы можете использовать 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);
     });
  });
}

С forEach вызовы срабатывают для каждого jsonString сразу и внутри негоawait работает, но forEach имеет тип возврата void, и этого нельзя ожидать, может только Future.

0 голосов
/ 21 декабря 2018

Вы определили обратный вызов для forEach как async, что означает, что он выполняется асинхронно.Другими словами: код внутри этого обратного вызова выполняется независимо от кода вне обратного вызова.Именно поэтому print("test"); запускается перед кодом внутри обратного вызова.

Самое простое решение - переместить весь код, которому требуется информация из обратного вызова , в обратный вызов.Но также может быть способ ожидать всех асинхронных обратных вызовов , аналогично тому, как вы уже await once вызываете над ним.

Обновление Я получил работу, что я думаю, что вы хотите сделать.С помощью этого 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
  }
}

я могу прочитать индекс, а затем объединить данные с помощью:

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"]);
  });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...