‘getDownloadURL’ возвращает на один URL меньше в обещании

#javascript #firebase #firebase-storage

#javascript #firebase #firebase-хранилище

Вопрос:

Я пытаюсь загрузить несколько изображений в хранилище Firebase и получить их URL-адреса, чтобы добавить их в качестве поля в профиле спортзала. Однако в коде, который я придумал, всегда не возвращается один URL. Если я загружаю 3 изображения, в хранилище появляются 3 изображения, но я получаю только 2 URL. Как мне это исправить?

 const promises = [];
const URLarray = [];

imageAsFile.forEach(img => {
            const uploadTask = storage.ref().child(`/photos/${doc.id}/${img.name}`).put(img);
            promises.push(uploadTask);
            uploadTask.then((uploadTaskSnapshot) => {
                return uploadTaskSnapshot.ref.getDownloadURL();
            }).then((pic) => {
                const addPics = db.collection("gyms").doc(doc.id)
                promises.push(addPics);
                addPics.update({gymPhoto: firebase.firestore.FieldValue.arrayUnion(pic)});
                // URLarray.push(pic)
            })
    });

Promise.all(promises).then(() => {
    // console.log(URLarray)
    alert("Done");
})
 

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

1. Promise.all(promises) всегда выполняется перед любым вызовом promises.push(addPics) . Кроме того, doc() не возвращает обещание, поэтому вы помещаете что-то, что не является обещанием, в свой массив promises. update() возвращает обещание, которое вы в данный момент игнорируете.

Ответ №1:

Должно работать следующее (непроверенное):

 const promises = [];

imageAsFile.forEach(img => {
    const uploadTask = storage.ref().child(`/photos/${doc.id}/${img.name}`).put(img);
    promises.push(uploadTask);
});

Promise.all(promises)
    .then(uploadTaskSnapshotsArray => {
        const promises = [];
        uploadTaskSnapshotsArray.forEach(uploadTaskSnapshot => {
            promises.push(uploadTaskSnapshot.ref.getDownloadURL());
        });

        return Promise.all(promises);
    })
    .then(urlsArray => {
        const docRef = db.collection("gyms").doc(doc.id);
        return docRef.update({ gymPhoto: firebase.firestore.FieldValue.arrayUnion(...urlsArray) });
    })
 

Promise.all() возвращает одно обещание: это обещание выполняется с помощью массива, содержащего все разрешенные значения в массиве, переданном в качестве аргумента.

Итак, если вы вызываете Promise.all() с массивом uploadTask s, когда возвращенное обещание будет выполнено, вы получите массив uploadTaskSnapshot s.

Затем вам нужно использовать этот массив для получения массива URL-адресов, снова используя Promise.all() .

Затем, когда вы получаете массив URL-адресов, вам нужно только один раз обновить документ с id = doc.id . Так что здесь вам не нужно Promise.all() . Что вам нужно сделать, так это передать FieldValue.arrayUnion() методу несколько значений. Для этого вам нужно использовать оператор распространения следующим образом:

 docRef.update({ gymPhoto: firebase.firestore.FieldValue.arrayUnion(...urlsArray) });