Escribí un código que recupera las direcciones URL de las imágenes almacenadas en mi depósito de Firebase Storage y las carga en una matriz imageUrls .
El código funciona en aproximadamente el 80% de los casos, pero para el resto (aparentemente el 20% aleatorio), cuando se ejecuta el código, no resuelve algunas promesas, pero tampoco genera una excepción.
Código:
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 (eg, "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 }) }) } La promesa que nunca se resuelve aparece arriba en la línea const imgUrl = await getDownloadURL(imgRef) .
Inserté declaraciones de registro de la consola en varios lugares para comprender los detalles de lo que está sucediendo. Todos los nombres de imágenes que esperaba se iteran en el bucle forEach y se crea una referencia imgRef para cada uno.
Sin embargo, en algunos casos, solo se resuelve un subconjunto de las promesas. En el resto, el código después de la instrucción await no se llama y, por lo tanto, la matriz imageUrls resultante contiene una combinación de cadenas de URL y valores null .
¿Por qué puede estar pasando esto? ¿Hay algo más que pueda hacer para aclarar más el problema? Gracias.
Puede intentar ejecutar esas promesas getDownloadURL() a la vez usando Promise.all() . Intente refactorizar el código como se muestra a continuación:
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); }Los valores devueltos de
Promise.all()estarán en el orden de las Promesas aprobadas, independientemente del orden de finalización.
Por lo tanto, no debería necesitar ordenar explícitamente usando index . Además, el filter() al final elimina cualquier valor null .
También consulte: Uso de async/await con un bucle forEach