Mark Nugromentry
Mark Nugromentry

Reputation: 304

Flutter Future Async Function - await stuck

I am calling a Future function that should add a document to firestore first, then to retrieve the doc id, then update the doc again with some paramaters.

I need to show a dialog for success or faliure. it is working fine for success case, but incorrect when testing failure .. I disconnect the internet before pressing the button then I press it to call the future function while internet is off to test failure scenario.

the problem is the future function stuck on the trying to add the document to firestore, it never fail and go to the failure scenario.

the below is future function code:

 Future CreateAccount() async {
  CollectionReference businessprofilescollectionref =
      FirebaseFirestore.instance.collection('BusinessProfilesCollection');

  DocumentReference docRef = await businessprofilescollectionref.add({
    'Profile_city': bpaddSelectedcity,
    'Profile_direct_category': directcategory,
  });

  if (docRef.id.isEmpty) {
    showDialog(context: context, builder: (_) => FailureDialog(context));
  }
  if (docRef.id.isNotEmpty) {
    String documentid = docRef.id.toString();
    print(documentid);
      FirebaseStorage storage = FirebaseStorage.instance;
      Reference ref = storage
          .ref()
          .child("BusinessProfileImages/$documentid".toString());
      UploadTask uploadTask = ref.putFile(bpaddimagefile);
      final snapshot = await uploadTask.whenComplete(() {});
      print("Image Uploaded");
      final urldownload = await snapshot.ref.getDownloadURL();
      print(urldownload);
      businessprofilescollectionref
          .doc(documentid)
          .update({'Profile_image_link': urldownload});
      print("Link Updated");
      await showDialog(
          context: context, builder: (_) => SuccessDialog(context));
      Navigator.of(context, rootNavigator: true).pop();
    }
 }

I tried to use timeout method like the below, this made the await ends, however the whole Future function is aborted and it doesn't continue executing the commands of showing the failure dialoge.

 DocumentReference docRef = await businessprofilescollectionref.add({
    'Profile_city': bpaddSelectedcity,
    'Profile_direct_category': directcategory,
  }).timeout(Duration(seconds: 20));

how can I solve this? I need to try to add the data to database, if that fails, I need to go to failure scenario and show a dialog.

Upvotes: 1

Views: 484

Answers (1)

Victor Eronmosele
Victor Eronmosele

Reputation: 7696

What went wrong:

You're checking if the ID of the DocumentReference is empty and using that as your failure scenario.

That will not work because when you get a DocumentReference back, it will have an ID. Here is a quote from the docs:

Returns a DocumentReference with an auto-generated ID, after populating it with provided data.

The above reason is why the docRef.id.isEmpty if statement is never executed because the ID is never empty.

How to fix it:

You should use a try-catch to wrap the add operation and implement the error scenario in the catch block.

Then you continue the rest of the operation in the docRef.id.isNotEmpty if statement right under the try-catch.

Update your CreateAccount function to this below:

Future CreateAccount() async {
  try {
    CollectionReference businessprofilescollectionref =
        FirebaseFirestore.instance.collection('BusinessProfilesCollection');

    DocumentReference docRef = await businessprofilescollectionref.add({
      'Profile_city': bpaddSelectedcity,
      'Profile_direct_category': directcategory,
    });
  } catch (e) {
    showDialog(context: context, builder: (_) => FailureDialog(context));
    return;
  }

  String documentid = docRef.id.toString();
  print(documentid);
  FirebaseStorage storage = FirebaseStorage.instance;
  Reference ref = storage.ref().child("BusinessProfileImages/$documentid".toString());
  UploadTask uploadTask = ref.putFile(bpaddimagefile);
  final snapshot = await uploadTask.whenComplete(() {});
  print("Image Uploaded");
  final urldownload = await snapshot.ref.getDownloadURL();
  print(urldownload);
  businessprofilescollectionref.doc(documentid).update({'Profile_image_link': urldownload});
  print("Link Updated");
  await showDialog(context: context, builder: (_) => SuccessDialog(context));
  Navigator.of(context, rootNavigator: true).pop();
}

Upvotes: 1

Related Questions