Функция загрузки Firebase работает по-разному каждый раз - PullRequest
0 голосов
/ 10 февраля 2020

У меня есть форма для загрузки нового элемента с несколькими полями и изображением. Я построил эту функцию так, что она сначала устанавливает новый документ в Firestore, затем загружает изображение, а затем сбрасывает форму.

Проблема в том, что он не всегда работает. Иногда изображение загружается, а иногда нет, даже если форма была сброшена (сброс обусловлен загрузкой изображения).

Это не соответствует, поэтому я не могу понять, что именно происходит.

Это функция загрузки:

export const newItem = (values, image, setValues) => () => {
  const newDoc = db.collection("items").doc();

  newDoc.set({ ...values, id: newDoc.id }).then(() => {
    storageRef
      .child(`images/items/${newDoc.id}`)
      .put(image)
      .then(result => {
        console.log(result);
        setValues({});
      });
  });
}; 

Я называю это следующим образом:

newItem({ ...values, is_public }, imageObj, setValues);

Тогда у меня есть эта облачная функция, которая добавляет URL для недавно загруженного файл в новый документ (но я не думаю, что проблема существует, потому что, когда я говорю, что изображение не было загружено, я имею в виду, что даже не вижу его в хранилище):

exports.writeFileToDatabase = functions.storage.object().onFinalize(object => {
  const bucket = defaultStorage.bucket();
  const path = object.name as string;
  const file = bucket.file(path);

  return file
    .getSignedUrl({
      action: "read",
      expires: "03-17-2025"
    })
    .then(results => {
      const url = results[0];
      const silcedPath = path.split("/", 3);

      switch (silcedPath[1]) {
        case "user-avatars":
          return db
            .collection("users")
            .doc(silcedPath[2])
            .set({ avatar: url }, { merge: true });

        case "items":
          return db
            .collection("items")
            .doc(silcedPath[2])
            .set({ image: url }, { merge: true });

        default:
          return null;
      }
    });
});

РЕДАКТИРОВАТЬ:

вот как я выбираю файл:

  <input
    id="image"
    className="new-item__upload"
    type="file"
    onChange={handleImageChange}
  />

Тогда это handleImageChange:

  const handleImageChange = e => {
    if (e.target.files[0]) {
      const image = e.target.files[0];
      setSelectedImage(URL.createObjectURL(image));
      setImageObj(image); // This is what end up being given to the function to upload
    }
  };

1 Ответ

1 голос
/ 10 февраля 2020

Вам необходимо правильно связать обещания, возвращаемые асинхронными операциями Firebase (set() и put()), следующим образом:

export const newItem = (values, image, setValues) => () => {
  const newDoc = db.collection("items").doc();

  newDoc.set({ ...values, id: newDoc.id })
   .then(() => {
     return storageRef         //Here return the Promise returned by the put() method
      .child(`images/items/${newDoc.id}`)
      .put(image);
   })
   .then(snapshot => {   
       console.log(snapshot);
       setValues({});
   })
   .catch(e => {
      console.error(e.message); 
      //You should throw an error here, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling
   });

};

Также рекомендуется добавить catch() вызов метода в конце цепочки Обещаний, чтобы получить более подробную информацию в случае ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...