Nats E
Nats E

Reputation: 63

Upload multiple images to firebase then save image url to firestore

Can someone assist me with revising the code so it will wait for the upload to finish then save the image urls to firestore? I'm new to async and await and can't seem to figure it out. The fileDownloadUrl is still empty even if I do the saving to firestore inside the Promise.all(promises).then():

cxonst promises = [];
const fileDownloadUrl = [];

pictures.forEach(file => {
    const uploadTask = 
    firebase
    .storage()
    .ref()
    .child(`img/upl/${file.data.name}`)
    .put(file.uploadTask);
    
    promises.push(uploadTask);

    uploadTask.on(
        
        firebase.storage.TaskEvent.STATE_CHANGED,
        snapshot => {
            const progress = Math.round((snapshot.bytesTransferred / 
                 snapshot.totalBytes) * 100);
            
            if (snapshot.state === firebase.storage.TaskState.RUNNING) {
                console.log(`Progress: ${progress}%`);
            }
        },
        error => console.log(error.code),
        async () => {
            const downloadURL = await 
            uploadTask.snapshot.ref.getDownloadURL();
            fileDownloadUrl.push(downloadURL);
            }
        );
    });

    Promise.all(promises)
    .then(() => {
        db
        .collection("properties")
        .add({
            timestamp: firebase.firestore.FieldValue.serverTimestamp(),
            title: title,
            description: description,
            pictures: fileDownloadUrl,
            user: user.uid
        })
    })
    .catch(err => console.log(err));

Upvotes: 0

Views: 851

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599956

While you are waiting for the promises of the put calls to complete, you're then using the uploadTask.on() to determine the download URL. Since this on is not part of the promise, there is no guarantee they're in sync.

A simpler and working approach should be:

const promises = pictures.map(file => {
  const ref = firebase.storage().ref().child(`img/upl/${file.data.name}`);
  return ref
    .put(file.uploadTask)
    .then(() => ref.getDownloadURL())
});

Promise.all(promises)
.then((fileDownloadUrls) => {
    db
    .collection("properties")
    .add({
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
        title: title,
        description: description,
        pictures: fileDownloadUrls,
        user: user.uid
    })
})
.catch(err => console.log(err));

Upvotes: 4

Related Questions