Будущее возвращает список перед заполнением

#flutter #asynchronous #firebase-realtime-database #async-await #future

#flutter #асинхронный #firebase-база данных в реальном времени #асинхронный -ожидание #будущее

Вопрос:

У меня есть следующий метод:

 Future<List<Job>> getUserJobs() async {
    Query query = _firebaseDatabase
        .reference()
        .child("jobs")
        .child(_firebaseAuth.currentUser.uid)
        .orderByKey();

    List<Job> userJobs = [];
    if (query == null) {
      return userJobs;
    }

    query.onValue.listen((event) {
      Map<dynamic, dynamic> values = event.snapshot.value;
      values.forEach((key, value) {
        userJobs.add(Job.fromJson(key, Map.from(value)));
      });
    });
    return userJobs;
  }
  

Я хочу получить этот ответ в другом классе, однако список, возвращаемый вышеуказанным методом, всегда равен [] . Я проверил, и список пользовательских заданий действительно заполнен, но оператор return выполняется раньше.

Структура базы данных такова: коллекция заданий имеет идентификаторы пользователей, и для каждого идентификатора пользователя у меня есть несколько ключей заданий (каждый со своими данными задания).

Ответ №1:

Попробуйте это:

 Future<List<Job>> getUserJobs() async {

  List<Job> userJobs = [];
//  Query query = 
  await _firebaseDatabase
      .reference()
      .child("jobs")
      .child(_firebaseAuth.currentUser.uid)
  .once()
      .orderByKey().then((result) async {
        if (result.value != null) {
          result.value.forEach((key, childSnapshot) {
            userJobs.add(Job.fromJson(key, Map.from(childSnapshot)));
          });
        } else {
        print(
            'getUserJobs() no jobs found');
        }
  }).catchError((e) {
      print(
          'getUserJobs() error: $e');
  });

  
//  if (query == null) {
//    return userJobs;
//  }

//  query.onValue.listen((event) {
//    Map<dynamic, dynamic> values = event.snapshot.value;
//    values.forEach((key, value) {
//      userJobs.add(Job.fromJson(key, Map.from(value)));
//    });
//  });
  return userJobs;
}
  

ваш цикл также должен быть асинхронным .. в противном случае метод вернется до завершения цикла, возвращая пустой список.. был там и был очень разочарован этим..
также всегда используйте .catchError обратный вызов .. он сообщает вам, что происходит не так 😉

Комментарии:

1. Это действительно работает! Единственное, что нужно было изменить, это то, что .orderByKey() должен быть before .once() в противном случае вы получите сообщение об ошибке. Приветствия!

2. Уверен .once() , что это тип запроса, поэтому он идет последним .. не заметил, что этого не было при редактировании вашего кода.. Рад, что смог помочь. Как я уже сказал, если вы выходите в Интернет, все становится немного сложнее, поскольку официальные пакеты для всех служб firebase еще недоступны.. дайте мне знать, если вам тоже понадобится помощь в этом.. Приветствия