【问题标题】:Flutter async/await is not working between 2 Firebase functionsFlutter async/await 在 2 个 Firebase 函数之间不起作用
【发布时间】:2020-04-21 16:25:56
【问题描述】:

我正在尝试调用一个云 Firestore 函数,该函数只有在另一个函数返回 Firebase 存储中文件的 url 但异步等待不起作用并且无论如何调用第二个函数而第一个函数时才保留一个对象还没完成!!!

      await schoolProfileProvider.uploadSchoolProfileAvatar(data).then( (data) {
          schoolProfileProvider.addSchoolProfile(data);
        });
        print('PROFILE ADDED');

Future<SchoolProfileData> uploadSchoolProfileAvatar(SchoolProfileData data) async {
    List<File> avatars = [];
    data.childrenDetails.forEach((child) {
      avatars.add(File(child.childImage));
    });
    try {
       await _api.uploadFilesToStorage(avatars, 'image', 'png').then((urls) {
        for (var i = 0; i < urls.length; i++) {
          data.childrenDetails[i].childImage = urls[i];
          print('ADD ' + data.childrenDetails[i].childImage);
        }
      });
    } on Exception catch (e) {
      print(e.toString());
    }
    return data;
  }

  T cast<T>(x) => x is T ? x : null;
  Future<List<String>> uploadFilesToStorage(List<File> files, String type, String extension) async {
    final urls = <Future<String>>[];
    files.forEach((file) async {
      StorageReference storageRef = storage.ref().child(file.path);
      final StorageTaskSnapshot downloadUrl =
      (await storageRef
          .putFile(file, StorageMetadata(contentType: type + '/' + extension))
          .onComplete);
       await downloadUrl.ref.getDownloadURL().then((url) {
        urls.add(cast<Future<String>>(url));
        print('URL for file ${file.path} = ${url.toString()}');
      });
    });
    print ('urls returned');
    return Future.wait(urls);
  }

  Future addSchoolProfile(SchoolProfileData data) async{
    var result;
    try {
      result = await _api.addDocument(data.toJson());
    } on Exception catch(e) {
      print (e.toString());
    }
    return result;
  }

【问题讨论】:

  • 这个问题需要减少到一个最小的可重复的例子,拜托。没有您的设置的人无法重现问题,而且问题发生的位置也不清楚。
  • 在示例顶部的方法调用的then 中,您调用了addSchoolProfile,但您不调用await。我想知道您是否认为第二种方法在第一种方法完成之前运行,因为您的程序在第二种方法完成之前打印了“PROFILE ADDED”。
  • 实际上,我希望只有在 schoolProfileProvider.uploadSchoolProfileAvatar(data) 完成并返回存储 url 列表时才执行异步函数 schoolProfileProvider.addSchoolProfile(data)
  • 您混合了两种不同的期货交易方式。在两者上尝试 async/await 或使用 .then(..) 链接。链接时,您需要从 .then(..) 块内部返回第二个未来。

标签: flutter dart


【解决方案1】:

只有在 uploadFilesToStorage 通过减少嵌套函数并使 await downloadUrl.ref.getDownloadURL() 完成后,我才设法使事情正常工作并执行 addSchoolProfile作为被调用函数中返回的最后一条指令。 有兴趣的请找代码:

调用者:

  schoolProfileProvider.addSchoolProfileAndUploadAvatar(data);

  Future addSchoolProfileAndUploadAvatar(SchoolProfileData data) async {
    List<File> avatars = [];
    data.childrenDetails.forEach((child) {
      avatars.add(File(child.childImage));
    });
    try {
         for (int i=0;i<avatars.length;i++){
           await _api.uploadFileToStorageAndGetUrl(avatars[i], 'image', 'png').then((url) {
             print('URL for file ${avatars[i].path} = ${url.toString()}');
             data.childrenDetails[i].childImage = url;
             print('ADD ' + data.childrenDetails[i].childImage);
           });
         }
         _api.addDocument(data.toJson()) ; // Add document in Google Firebase after setting the avatar url
    } on Exception catch (e) {
      print(e.toString());
    }
  }

被调用者:

Future <String>  uploadFileToStorageAndGetUrl(File file,String type, String extension) async{
    StorageReference storageRef = storage.ref().child(file.path);
    final StorageTaskSnapshot downloadUrl =
    (await storageRef
            .putFile(file, StorageMetadata(contentType: type + '/' + extension))
    .onComplete);
    return await downloadUrl.ref.getDownloadURL(); // return the url of the file in Google Storage
  }

【讨论】:

    猜你喜欢
    • 2020-12-07
    • 2021-08-03
    • 2018-10-17
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 2015-09-28
    • 2020-07-12
    • 2021-08-06
    相关资源
    最近更新 更多