Странное значение null, возвращаемое асинхронной функцией формы

# #flutter #url #google-cloud-firestore #storage

Вопрос:

Я пытаюсь получить URL загруженного файла изображения в хранилище firebase, но сталкиваюсь с очень странным поведением.

Пожалуйста, взгляните на приведенный ниже код, проблема объясняется в комментариях:

 Futurelt;String?gt; _uploadImage(String fileName, File imageFile) async {  try {  // Uploading the selected image with some custom meta data  await FirebaseStorage.instance  .ref(fileName)  .putFile(  imageFile,  SettableMetadata(customMetadata: {  'uploaded_by': 'Some guy',  'description': 'Some description...'  }))  .then((imgUploadTaskSnapshot) async {  switch (imgUploadTaskSnapshot.state) {  case TaskState.paused:  break;  case TaskState.running:  break;  case TaskState.success:  return await FirebaseStorage.instance.ref(fileName).getDownloadURL().then((fileURL) {  print('url : $fileURL'); // here i get a value -gt; url : https://firebasest.....  return fileURL; // but here null is returned  });  break;  case TaskState.canceled:  break;  case TaskState.error:  break;  }  });  } on FirebaseException catch (error) {  //Todo: handle errors  print(error);  throw error;  } }  Futurelt;Listlt;Stringgt;?gt; uploadImages(Listlt;Maplt;String, dynamicgt;gt; images) async {  try {  Listlt;Stringgt; imgsURLs = lt;Stringgt;[];  for (int i = 0; i lt; images.length; i  ) {  await _uploadImage(images[i]['filename'], images[i]['imagefile'])  .then((imgURL) {  print('imgURL: $imgURL'); // cause here i get -gt; imgURL: null  if (imgURL != null) {  imgsURLs.add(imgURL);  }  });  }  print('imgsURLs: $imgsURLs');  return imgsURLs;  } on FirebaseException catch (error) {  //Todo: hadle errors  print(error);  throw error;  } }  

Ответ №1:

Это происходит потому, что тело в then обратном вызове-это другая функция. Таким образом, вызов return внутри него вернет значение, но не для _uploadImage , а для анонимного обратного вызова.

Возвращенное значение фактически появится в результате ожидания обратного вызова. Вы можете добавить возврат, чтобы в дальнейшем вернуть его в результате _uploadImage

 return await FirebaseStorage.instance.ref(fileName).getDownloadURL().then(...  

Что также стоит отметить, так это то, что вам не нужно использовать then , когда вы находитесь в асинхронной функции. Это главное преимущество их наличия — вам не нужно иметь дело с обратными вызовами.

 Futurelt;String?gt; _uploadImage(String fileName, File imageFile) async {  try {  // Uploading the selected image with some custom meta data  final imgUploadTaskSnapshot = await FirebaseStorage.instance  .ref(fileName)  .putFile(  imageFile,  SettableMetadata(customMetadata: {  'uploaded_by': 'Some guy',  'description': 'Some description...'  }));   switch (imgUploadTaskSnapshot.state) {  case TaskState.paused:  break;  case TaskState.running:  break;  case TaskState.success:  final fileURL =  await FirebaseStorage.instance.ref(fileName).getDownloadURL();  return fileURL;  case TaskState.canceled:  break;  case TaskState.error:  break;  }  } on FirebaseException catch (error) {  //Todo: handle errors  print(error);  throw error;  } }  

Комментарии:

1. Большое спасибо за ваш ответ. Я уверен, что это поможет. Я просто на самом деле отсутствую несколько дней, поэтому я подожду, пока вернусь, чтобы проверить свое приложение, прежде чем закрыть тему. Еще раз большое спасибо

2. Привет, pr0gramist, я изменил код, как вы предложили, но у меня все еще тот же результат.

3. Трудно догадаться, что может быть не так. Вы можете обновить код или явно добавить типы, чтобы определить проблему.