skip to Main Content

I am struggling with futures and nested futures. I need to wait for the loadRecordData before it is returned as it is not loaded when trying to display it in a FutureBuilder/List

This reads records from the database and returns them in a list

Future<List<Record>> readRecords(Query query) async {
  final dbHelper = DatabaseHelper();
  final db = await dbHelper.database;

  final List<Map<String, dynamic>> maps = await db.rawQuery(query.sql,query.params);

  return List.generate(maps.length, (i) {
    return fillRecord(maps[i]);
  });
}

This fills the Record Class with the fields from the query, and then depending on what type of record is loaded, load more data using more database queries.

I think the issue I have is I am not waiting for loadRecordData to complete. I have tried making this function async, but then it needs to return a future, which bubbles up and requires the list above to also be a list of futures.

Record fillRecord(map)  {
  Record rec = Record(
      id: map['id'],
      recordType: map['recordType'],
      title: map['title'],
      url: map['url'].toString(),
      imageUrl: map['imageUrl'],
  );

  // await rec.loadRecordData();
  // return rec;

    // I think this is the problem area. I need to wait for this function to complete, but cannot make it work.
    rec.loadRecordData(); 

    return p;
}

This is part of the Record class to update record with extra data

Future<void> loadRecordData() async {
    readRecordMetas(id).then((ListRecordMeta> myMeta) async {
      metaData = myMeta;
      if (postType == 'event') {
        String? orgId = getMetaValue("organisation");
        if (orgId != null) {
          readRecord(orgId).then((Record? org) async {
            eventOrganisation = org;
          });
        }
      }
    });
    

How can I be sure that loadRecordData completes before returning list;

2

Answers


  1. You are not awaiting all async calls that you are making. I would rewrite loadRecordData to

    Future<void> loadRecordData() async {
      metaData =  await readRecordMetas(id);
      if (postType == 'event') {
        String? orgId = getMetaValue("organisation");
        if (orgId != null) {
          eventOrganisation = await readRecord(orgId);
        }
      }
    }
    

    And then fillRecord as

    Future<Record> fillRecord(map) async {
      Record rec = Record(
          id: map['id'],
          recordType: map['recordType'],
          title: map['title'],
          url: map['url'].toString(),
          imageUrl: map['imageUrl'],
      );
    
      await rec.loadRecordData();
      return rec;
    
    }
    

    and finally inside readRecords change

      return List.generate(maps.length, (i) {
        return fillRecord(maps[i]);
      });
    

    to

      return await Future.wait(maps.values.map((i) => fillRecord(i)));
    
    Login or Signup to reply.
  2. try this:

    Future<void> loadRecordData() async {
      final recordMetas = await readRecordMetas(id);
      if (postType == 'event') {
        String? orgId = getMetaValue("organisation");
        if (orgId == null) return; 
        eventOrganisation = await readRecord(orgId);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search