Function returning before future completion

Krishnanand V P :

I have a function. I want this function to return a List of Meals. My intention is to get a list of Meal objects created from firebase. I want to use this List of Meals to Create another object Store.

Future<List<Meal>> mealListGen(String storeId) async{
  List<Meal> mealListTest=[];
  Future<List<Meal>> finalMealList=  DatabaseService().storeCollection.document(storeId).get().then((doc){

    List<String> result = List.from(doc['meals']);

    print('The list is ${result[0]}');

    result.forEach((mealId) async{

      print('meal id is $mealId');

      Meal meal= await mealFromDb(mealId);

      print('${meal.name} is added');

      mealListTest.add(meal);
    });
    return mealListTest;
  });
  return finalMealList;
}// print(finalMealList[0]);

When I execute the function Like this

mealListGen('s1').then((res){
              print(res[0].name);
});

I get this output in LogCat

I/flutter (32035): The list is m1
I/flutter (32035): meal id is m1
E/flutter (32035): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0
[38;5;244mE/flutter (32035): #0      List.[]  (dart:core-patch/growable_array.dart:149:60)[39;49m
[38;5;248mE/flutter (32035): #1      MyAppBar.build.<anonymous closure>.<anonymous closure>[39;49m
[38;5;244mE/flutter (32035): #2      _rootRunUnary  (dart:async/zone.dart:1134:38)[39;49m
[38;5;244mE/flutter (32035): #3      _CustomZone.runUnary  (dart:async/zone.dart:1031:19)[39;49m
[38;5;244mE/flutter (32035): #4      _FutureListener.handleValue  (dart:async/future_impl.dart:139:18)[39;49m
[38;5;244mE/flutter (32035): #5      Future._propagateToListeners.handleValueCallback  (dart:async/future_impl.dart:680:45)[39;49m
[38;5;244mE/flutter (32035): #6      Future._propagateToListeners  (dart:async/future_impl.dart:709:32)[39;49m
[38;5;244mE/flutter (32035): #7      Future._completeWithValue  (dart:async/future_impl.dart:524:5)[39;49m
[38;5;244mE/flutter (32035): #8      _AsyncAwaitCompleter.complete  (dart:async-patch/async_patch.dart:32:15)[39;49m
[38;5;244mE/flutter (32035): #9      _completeOnAsyncReturn  (dart:async-patch/async_patch.dart:290:13)[39;49m
E/flutter (32035): #10     DocumentReference.get (package:cloud_firestore/src/document_reference.dart)
[38;5;244mE/flutter (32035): #11     _asyncThenWrapperHelper.<anonymous closure>  (dart:async-patch/async_patch.dart:73:64)[39;49m
[38;5;244mE/flutter (32035): #12     _rootRunUnary  (dart:async/zone.dart:1134:38)[39;49m
[38;5;244mE/flutter (32035): #13     _CustomZone.runUnary  (dart:async/zone.dart:1031:19)[39;49m
[38;5;244mE/flutter (32035): #14     _FutureListener.handleValue  (dart:async/future_impl.dart:139:18)[39;49m
[38;5;244mE/flutter (32035): #15     Future._propagateToListeners.handleValueCallback  (dart:async/future_impl.dart:680:45)[39;49m
[38;5;244mE/flutter (32035): #16     Future._propagateToListeners  (dart:async/future_impl.dart:709:32)[39;49m
[38;5;244mE/flutter (32035): #17     Future._completeWithValue  (dart:async/future_impl.dart:524:5)[39;49m
[38;5;244mE/flutter (32035): #18     _AsyncAwaitCompleter.complete  (dart:async-patch/async_patch.dart:32:15)[39;49m
[38;5;244mE/flutter (32035): #19     _completeOnAsyncReturn  (dart:async-patch/async_patch.dart:290:13)[39;49m
E/flutter (32035): #20     MethodChannelDocumentReference.get (package:cloud_firestore_platform_interface/src/method_channel/method_channel_document_reference.dart)
[38;5;244mE/flutter (32035): #21     _asyncThenWrapperHelper.<anonymous closure>  (dart:async-patch/async_patch.dart:73:64)[39;49m
[38;5;244mE/flutter (32035): #22     _rootRunUnary  (dart:async/zone.dart:1134:38)[39;49m
[38;5;244mE/flutter (32035): #23     _CustomZone.runUnary  (dart:async/zone.dart:1031:19)[39;49m
[38;5;244mE/flutter (32035): #24     _FutureListener.handleValue  (dart:async/future_impl.dart:139:18)[39;49m
[38;5;244mE/flutter (32035): #25     Future._propagateToListeners.handleValueCallback  (dart:async/future_impl.dart:680:45)[39;49m
[38;5;244mE/flutter (32035): #26     Future._propagateToListeners  (dart:async/future_impl.dart:709:32)[39;49m
[38;5;244mE/flutter (32035): #27     Future._completeWithValue  (dart:async/future_impl.dart:524:5)[39;49m
[38;5;244mE/flutter (32035): #28     _AsyncAwaitCompleter.complete  (dart:async-patch/async_patch.dart:32:15)[39;49m
[38;5;244mE/flutter (32035): #29     _completeOnAsyncReturn  (dart:async-patch/async_patch.dart:290:13)[39;49m
E/flutter (32035): #30     MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart)
[38;5;244mE/flutter (32035): #31     _asyncThenWrapperHelper.<anonymous closure>  (dart:async-patch/async_patch.dart:73:64)[39;49m
[38;5;244mE/flutter (32035): #32     _rootRunUnary  (dart:async/zone.dart:1134:38)[39;49m
[38;5;244mE/flutter (32035): #33     _CustomZone.runUnary  (dart:async/zone.dart:1031:19)[39;49m
[38;5;244mE/flutter (32035): #34     _FutureListener.handleValue  (dart:async/future_impl.dart:139:18)[39;49m
[38;5;244mE/flutter (32035): #35     Future._propagateToListeners.handleValueCallback  (dart:async/future_impl.dart:680:45)[39;49m
[38;5;244mE/flutter (32035): #36     Future._propagateToListeners  (dart:async/future_impl.dart:709:32)[39;49m
[38;5;244mE/flutter (32035): #37     Future._completeWithValue  (dart:async/future_impl.dart:524:5)[39;49m
[38;5;244mE/flutter (32035): #38     _AsyncAwaitCompleter.complete  (dart:async-patch/async_patch.dart:32:15)[39;49m
[38;5;244mE/flutter (32035): #39     _completeOnAsyncReturn  (dart:async-patch/async_patch.dart:290:13)[39;49m
E/flutter (32035): #40     MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart)
[38;5;244mE/flutter (32035): #41     _asyncThenWrapperHelper.<anonymous closure>  (dart:async-patch/async_patch.dart:73:64)[39;49m
[38;5;244mE/flutter (32035): #42     _rootRunUnary  (dart:async/zone.dart:1134:38)[39;49m
[38;5;244mE/flutter (32035): #43     _CustomZone.runUnary  (dart:async/zone.dart:1031:19)[39;49m
[38;5;244mE/flutter (32035): #44     _FutureListener.handleValue  (dart:async/future_impl.dart:139:18)[39;49m
[38;5;244mE/flutter (32035): #45     Future._propagateToListeners.handleValueCallback  (dart:async/future_impl.dart:680:45)[39;49m
[38;5;244mE/flutter (32035): #46     Future._propagateToListeners  (dart:async/future_impl.dart:709:32)[39;49m
[38;5;244mE/flutter (32035): #47     Future._completeWithValue  (dart:async/future_impl.dart:524:5)[39;49m
[38;5;244mE/flutter (32035): #48     Future._asyncComplete.<anonymous closure>  (dart:async/future_impl.dart:554:7)[39;49m
[38;5;244mE/flutter (32035): #49     _rootRun  (dart:async/zone.dart:1126:13)[39;49m
[38;5;244mE/flutter (32035): #50     _CustomZone.run  (dart:async/zone.dart:1023:19)[39;49m
E/flutter (32035): #51     _CustomZone.runGuarded (dart:async/zone
I/flutter (32035): Pepporoni Pizza is added

Looks Like the function return before the future completion what should I do to make the function return a List.

user8773560 :

This is the best way to use Future

  1. You must awaitthe first request by either calling

    var result = await someFuture();
    

or

await someFuture().then((result){});
//Here result is ithe tasks result
  1. When you have multiple Futures wich you want to wait for then ending, the more efficient way is either by calling

    List<YourType> result = await Future.forEach(yourListHere,(yourListItem) async=>await oneFutureForEachItem());
    

or

await Future.forEach(yourListHere,(yourListItem) async=>await oneFutureForEachItem()).then((result){});//this is your list of results

Now let use them for your case

Future<List<Meal>> mealListGen(String storeId) async {
  List<Meal> mealListTest = [];
   await DatabaseService().storeCollection.document(storeId).get().then((doc){

  List<String> result = List.from(doc['meals']);

  print('The list is ${result[0]}');
//Now we have to get details of meals by their ids
//Future.forEach is in charg of calling the mealFromDb for each item in our list
//This helps us getting all results from just one call and duration of this feature is based  on the longest instead of been sum of all duratins. So, i'll be more efficient and speed
  mealListTest =  await Future.forEach(result, (mealId) async {
    print('meal id is $mealId');

    return mealFromDb(mealId);
  });
   });
  return mealListTest;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=220373&siteId=1