Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to turn a List<Future<E>> to a List<E>?

I have a List of classes of type Section, and inside of Section there is a property chapter of type Chapter. I need to do some asynchronous operation to fill one property of Chapter, but if I do it then the new List will turn to a List<Future<Chapter>> and will not be able to remove the Future inside the List elements. How can I solve this?

Here the code:

  Future<void> createCourse(Course course) async {
    final storageRef = FirebaseStorage.instance.ref();
    final sections = course.sections!.toList();

    List<Future<Section>> sectionsNew = sections.map((section) async {
      List<Future<Chapter>> chaptersNew =
          section.chapters!.map((chapter) async {
        if (chapter.type == "video") {
          final image = storageRef
              .child("images/${chapter.chapterNumber}.${chapter.name}")
              .putData(chapter.videoBytes!);

          return Chapter(
            videoUrl: await image.storage.ref().getDownloadURL(), // here the async operation
            name: chapter.name,
            type: chapter.type,
            duration: chapter.duration,
            chapterNumber: chapter.chapterNumber,
          );
        } else {
          return Chapter(
            textBody: chapter.textBody,
            name: chapter.name,
            type: chapter.type,
            duration: chapter.duration,
            chapterNumber: chapter.chapterNumber,
          );
        }
      }).toList();

      return section.copyWith(
          chapters:
              chaptersNew); // The argument type 'List<Future<Chapter>>' can't be assigned to the parameter type 'List<Chapter>?'.
    }).toList();

    await coursesCollection.add(
      {
        "name": course.name,
        "price": course.price,
        "level": course.level,
        "language": course.language,
        "duration": course.duration,
        "active": course.active,
        "description": course.description,
        "image": course.imageBase64,
        "teacher_uid": course.teacherUid,
        "sections": sectionsNew.cast<Section>(),
      },
    );
  }

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

To turn a List<Future<E>> into a List<E>, you can use the Future.wait method, which takes a list of futures and waits for all of them to complete. It returns a future that completes with a list of the results. Here’s how you can modify your code to achieve this:

Future<void> createCourse(Course course) async {
  final storageRef = FirebaseStorage.instance.ref();
  final sections = course.sections!.toList();

  List<Future<Section>> sectionsNew = sections.map((section) async {
    List<Future<Chapter>> chaptersNew =
        section.chapters!.map((chapter) async {
      if (chapter.type == "video") {
        final image = storageRef
            .child("images/${chapter.chapterNumber}.${chapter.name}")
            .putData(chapter.videoBytes!);

        return Chapter(
          videoUrl: await image.storage.ref().getDownloadURL(), // here the async operation
          name: chapter.name,
          type: chapter.type,
          duration: chapter.duration,
          chapterNumber: chapter.chapterNumber,
        );
      } else {
        return Chapter(
          textBody: chapter.textBody,
          name: chapter.name,
          type: chapter.type,
          duration: chapter.duration,
          chapterNumber: chapter.chapterNumber,
        );
      }
    }).toList();

    // Use Future.wait to wait for all the chapter futures to complete.
    List<Chapter> chaptersResolved = await Future.wait(chaptersNew);

    return section.copyWith(
        chapters: chaptersResolved);
  }).toList();

  await coursesCollection.add(
    {
      "name": course.name,
      "price": course.price,
      "level": course.level,
      "language": course.language,
      "duration": course.duration,
      "active": course.active,
      "description": course.description,
      "image": course.imageBase64,
      "teacher_uid": course.teacherUid,
      "sections": sectionsNew.cast<Section>(),
    },
  );
}

In the code above, we use Future.wait to wait for all the chapter futures in each section to complete, and then we get a list of resolved chapters. This way, you’ll have a List<Section> where each section contains a List<Chapter> without the Future wrappers.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading