Home > Enterprise >  Firebase Storage Promise Not Being Resolved
Firebase Storage Promise Not Being Resolved

Time:05-02

I wrote code that retrieves urls of images stored in my Firebase Storage bucket and loads them in an imageUrls array.

The code works in about 80% of instances, but for the remaining (seemingly random 20%), when the code is run, it fails to resolve some promises, but doesn't throw an exception either.

Code:

async function loadImages() {
    // Load image urls from firebase storage
    Object.values(imageOrder).forEach(async (fileName, index) => { // Iterate through each imageName for image that should be loaded (e.g., "dogs.jpg", "mountains.jpeg")
        const imgRef = ref(storage, `images/projects/${project.id}/draft/${fileName}`)
        const imgUrl = await getDownloadURL(imgRef) // this promise may never get resolved for some iterations of the loop
        const imgPos = index // store index in array at which this image should be inserted into

        setImageUrls(prevState => {
            let newArray = [...prevState]
            newArray = newArray.map((item, index) => index === imgPos ? imgUrl : item) // replace null value in array with loaded image url at appropriate index
            return newArray
        })
    })
}

The promise that never gets resolved appears above in the line const imgUrl = await getDownloadURL(imgRef).

I inserted console log statements at various places to understand the details of what is happening. All image names I expected are iterated through in the forEach loop, and an imgRef reference is created for each.

In some cases though, only a subset of the promises get resolved. In the rest, the code after the await statement does not get called, and therefore the resulting imageUrls array contains a combination of url strings as well as null values.

Why may this be happening? Is there anything else I can do to clarify the problem further? Thanks.

CodePudding user response:

You can try running those getDownloadURL() promises at once using Promise.all(). Try refactoring the code as shown below:

async function loadImages() {
    // Load image urls from firebase storage
    const promises = [];
    
    Object.values(imageOrder).forEach(image => {
        const imgRef = ref(storage, `images/projects/${project.id}/draft/${fileName}`);
        promises.push(getDownloadURL(imgRef));
    })

    const urls = (await Promise.all(promises)).filter(url => !!url);

    setImageUrls(urls);
}

Returned values from Promise.all() will be in order of the Promises passed, regardless of completion order.

So you shouldn't need to explicitly sort using index. Also the filter() at end removes any null values.

Also checkout: Using async/await with a forEach loop

  • Related