Dart — помогите мне понять, как работает этот код в Dart

Пожалуйста, помогите мне понять, как работает этот код. И почему это так работает.

Переменные res в примере это Stream<Row>.

Я хочу вернуть Future<List> из метода processQueryResult. Этот код работает так, как должен, и результат, который я получаю, правильный.

Пример 1

Future<List> processQueryResult(mysql.Results res) {
  List data = [];

  res.toList().then((List<mysql.Row> rows) {
    rows.forEach((mysql.Row row) {
      data.add({name: row.name, email: row.email});
    });
  });

  return new Future<List>(() {
    return data;
  });
}

В результате data содержит все необходимые данные.

Но подскажите пожалуйста, почему когда я перемещаю эту часть кода

res.toList().then((List<mysql.Row> rows) {
  rows.forEach((mysql.Row row) {
    data.add({name: row.name, email: row.email});
  });
});

To

return new Future<List>(() {

  res.toList().then((List<mysql.Row> rows) {
    rows.forEach((mysql.Row row) {
      data.add({name: row.name, email: row.email});
    });
  });

  return data;

});

Наконец код выглядит так (Пример 2):

Future<List> processQueryResult(mysql.Results res) {
  List data = [];      

  return new Future<List>(() {
    res.toList().then((List<mysql.Row> rows) {
      rows.forEach((mysql.Row row) {
       data.add({name: row.name, email: row.email});
      });
    });

    return data;
  });
}

Тогда в результате я получаю пустой список.

Для теста я использую эту функцию:

testResult() {

  mysql.Results res = ... // get results;
  processQueryResult(res).then((data) {
    print(data);
  })

}

Когда код processQueryResult похож на Пример 1, то я получаю правильные данные, но когда код processQueryResult похож на Пример 2 - я получаю пустой список.

Скажите, пожалуйста, почему это происходит?

Буду рад, если дадите ссылку на соответствующую статью или документацию.


person J Sorel    schedule 24.10.2014    source источник


Ответы (1)


return new Future<List>(() {

  res.toList() // <== 1.) registers a future for later execution // <== 3.) execute `toList()`
    .then((List<mysql.Row> rows) {
    rows.forEach((mysql.Row row) { // <== 4.) execute rows.forEach
      data.add({name: row.name, email: row.email});
    });
  });

  return data; // <== 2.) return data

});

3.) выполняется после того, как код, вызывающий вышеуказанный код, завершил выполнение всей синхронизации

return new Future<List>(() {

  return res.toList() // <== returning the future keeps the async parts connected
                      // and one is executed after the other
    .then((List<mysql.Row> rows) {
      rows.forEach((mysql.Row row) { // <== 4.) execute rows.forEach
        data.add({name: row.name, email: row.email});
      });
    })
    .then((_) data);  // <== the same here, return data **after** the previous statements are finished
  });
});
person Günter Zöchbauer    schedule 24.10.2014
comment
Большое спасибо за помощь! Ты самый крутой человек на stackoverflow! - person J Sorel; 24.10.2014
comment
Спасибо! Рад, что смог помочь. - person Günter Zöchbauer; 24.10.2014