Future returns list before being populated
Asked Answered
K

1

0

I have the following method:

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;
  }

I want to get this response in another class, however, the list returned by the above method is always []. I checked and the userJobs list is indeed populated but the return statement is executed before.

The structure of the database is: Job collection has user IDs and for each user ID I have several job keys (each with its job data).

Konstantine answered 9/10, 2020 at 10:7 Comment(0)
K
1

Try this:

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;
}

your loop also needs to be async..otherwise the method will return before the loop finishes, returning the empty List.. been there and got quite frustrated by this.. also always use .catchError callback.. it tells you what's going wrong ;)

Kinch answered 9/10, 2020 at 10:28 Comment(2)
It does indeed work! The only one thing that needed change was that .orderByKey() should be before .once() otherwise you get an error. Cheers!Konstantine
Sure .once() is the query type so it goes last.. didn't noticed it wasn't while editing your code.. Glad I could help. As I said if you go web things get a bit complicated as official packages for all firebase services aren't yet available.. let me know if you need help with that too..CheersKinch

© 2022 - 2024 — McMap. All rights reserved.