如何确保 future 及其所有子 future 调用在继续执行之前完成

Mad*_*Max 1 async-await dart google-cloud-storage flutter google-cloud-firestore

我有一种方法将照片上传到 firebase 云存储,然后获取照片的下载 url,然后使用该 url 更新 firebase 数据库文档。当我使用uploadProfilePhoto(..)时,我的问题出现在ElevatedButton回调中。然后在setPersonalPhotoUrl()方法完成其工作并设置individualPhotoUrl之前执行代码。

我尝试使用whenComplete代替,但它不起作用。我的想法(如果没有错误的话)是uploadProfilePhoto(..).then正在完成其未来,但它没有考虑未来方法setPersonalPhotoUrl()的完成。我需要这方面的帮助。

声明的字段:

 UploadTask? uploadTask;
 String personalPhotoUrl = '';
Run Code Online (Sandbox Code Playgroud)

更新按钮:

                          ElevatedButton(
                          child: Text('Update Info'),
                          onPressed: () async {
                            await uploadProfilePhoto(profilePhotoFile).then((value) async {
                              // Create an instance of ServiceProvider
                              final SP = ServiceProvider(
                                id: currentUserUid!,
                                name: _controllerName.text.trim(),
                                last: _controllerLast.text.trim(),
                                mobile: _controllerMobile.text.trim(),
                                bio: _controllerBio.text.trim(),
                                photo: personalPhotoUrl, //problem here the value is ''
                                serviceId: _selectedServiceId!,
                                subServices: _selectedSubServicesList,
                              );

                              // Create or Update the service provider
                              try {
                                await DbServices(uid: currentUserUid!)
                                    .updateSProviderData(SP)
                                    .then((value) async {
                                  // update the customers collection when the future completes.
                                  final customer = Customer(
                                      uid: currentUserUid!,
                                      name: _controllerName.text.trim(),
                                      isServiceProvider: true);
                                  await DbServices(uid: currentUserUid!).updateCustomer(customer);
                                  // update the user displayname in firebaseauth when the future completes.
                                  final user = await FirebaseAuth.instance.currentUser;
                                  if (user != null) {
                                    await user.updateDisplayName(_controllerName.text.trim());
                                  }
                                });
                              } catch (e) {
                                Utils.ShowSnackBar(e.toString());
                              }
                            });

                            Utils.ShowSnackBar('Updated successfully');
                            Navigator.maybePop(context).then((value) {
                              if (value == false) {
                                Navigator.pushReplacement(
                                    context,
                                    MaterialPageRoute(
                                      builder: (context) => Home(),
                                    ));
                              }
                            });
                          })
Run Code Online (Sandbox Code Playgroud)

这是上传照片方法,它将给定的照片上传到 FiresStore 云存储:

  Future uploadProfilePhoto(File? photoFile) async {
      if (photoFile == null) return;
      const path = 'images/profile_photo.jpg';
      final storageRef = FirebaseStorage.instance.ref().child(path);
  
      try {
        uploadTask = storageRef.putFile(photoFile);
        uploadTask?.snapshotEvents.listen((TaskSnapshot taskSnapshot) async {
          switch (taskSnapshot.state) {
            ....
            case TaskState.success:
              setPersonalPhotoUrl(storageRef);
              break;
          }
        });
      } on FirebaseException catch (e) {
        // do something
        print('ERROR: Exception thrown when uploading the image: $e');
      }
  }
Run Code Online (Sandbox Code Playgroud)

这个方法将从uploadProfilePhoto中调用并设置 url:

  void setPersonalPhotoUrl(Reference storageRef) async {
      personalPhotoUrl = await storageRef.getDownloadURL();
  }
Run Code Online (Sandbox Code Playgroud)

在确保照片上传之前,我不会更新数据库文档,稍后我想通知用户,如果照片上传失败,然后可能将文档字段设置为空字符串

The*_*MCA 5

1. 将你的上传功能重构为。

Future uploadProfilePhoto(
      File? photoFile, ValueSetter<TaskSnapshot> resultCallBack) async {
    if (photoFile == null) return;
    const path = 'images/profile_photo.jpg';
    final storageRef = FirebaseStorage.instance.ref().child(path);

    try {
      UploadTask? uploadTask = storageRef.putFile(photoFile);
      uploadTask.snapshotEvents.listen((TaskSnapshot taskSnapshot) async {
        resultCallBack(taskSnapshot);
      });
    } on FirebaseException catch (e) {
      // do something
      print('ERROR: Exception thrown when uploading the image: $e');
    }
  }
Run Code Online (Sandbox Code Playgroud)

2.然后可以像这样使用它

onPressed: () async {
      await uploadProfilePhoto(
          profilePhotoFile, (TaskSnapshot taskSnapshotResult) {
        // all the results you need are available in taskSnapshotResult
            if(taskSnapshotResult.state == TaskState.success){
              /// can do what ever you like here

         .... // Create an instance of ServiceProvider
                          final SP = ServiceProvider( ..... blah blah blah
                           
            }
          });
}
Run Code Online (Sandbox Code Playgroud)