• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Evaluaciones
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

128
Vistas
Javascript: cómo esperar a que se resuelvan varias promesas dentro de un bucle antes de seguir adelante

Vi preguntas similares, pero me cuesta aplicarlas a mi código.

Tengo el siguiente fragmento de código:

 createSubmission(sub: Submission, files: Files[]): Promise { //first add files to storage and create the url array let urlArray: string[]; return files.forEach(file => { var storageRef = this.storage.ref(`files/${file.name}`); return storageRef.put(file).then(()=> {storageRef.getDownloadURL().subscribe(url => { urlArray.push(url); if(urlArray.length === files.length){ //we are at the final element sub.filesUrls = urlArray; return this.finilize(sub); } }) }); }); } finilize(sub: Submission){ //actually creates the submission let subRef = this.db.database.ref(`/submissions/${sub.medicUid}`).push(); let subKey = subRef.getKey(); sub.uid = subKey; return subRef.update(sub); }

La persona que llama al primer método ( createSubmission ) debe recibir una Promesa. Mi secuencia de código finaliza cuando finilize del método de finalización.

Quiero continuar después de que se hayan iterado todos los elementos en el bucle y se haya llenado el urlArray . Se llena cuando tiene la misma cantidad de elementos que la matriz de files pasada, por eso puse esta condición:

if(urlArray.length === files.length){...}

Sin embargo, recibo un error porque la condición if significa que No todas las rutas de código devuelven un valor. Así que creo que debería deshacerme de la condición if y esperar a que se resuelvan todas las promesas antes de llamar a finalize , pero no tengo muy claro cómo hacerlo.

almost 3 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

En primer lugar, el bucle foreach no devuelve nada, sino que modifica la matriz existente.

Ahora ven a la solución.

no puede usar forEach cuando desea que su código espere algún evento asíncrono. En su lugar, use un bucle for of, y con ese uso await

 async createSubmission(sub: Submission, files: Files[]): Promise { //first add files to storage and create the url array let urlArray: string[]; for (const file of files) { const url = await this.getDownloadURL(file) urlArray.push(url) } sub.filesUrls = urlArray return this.finilize(sub) } getDownloadURL(file):Promise{ let storageRef = this.storage.ref(`files/${file.name}`); return new Promise((resolve, reject) => { storageRef.put(file).then(() => { storageRef.getDownloadURL().subscribe(url => { resolve(url) }) }) }) } finilize(sub: Submission){ //actually creates the submission let subRef = this.db.database.ref(`/submissions/${sub.medicUid}`).push(); let subKey = subRef.getKey(); sub.uid = subKey; return subRef.update(sub); }

Nota: el fragmento de código puede contener errores sintácticos

almost 3 years ago · Juan Pablo Isaza Denunciar

0

No sé de qué es storageRef.getDownloadURL() (supongo que está relacionado con Firebase y Angular), así que dejo la mayor parte de su código intacto, asumiendo que es correcto y que solo quiere saber cómo tratar correctamente con el Caso de promesa.

Hay dos formas de resolver el problema.

  1. Procesando los archivos secuencialmente usando await/async
 async createSubmission(sub: Submission, files: Files[]): Promise { //first add files to storage and create the url array let urlArray: string[]; for( let file of files ) { const storageRef = this.storage.ref(`files/${file.name}`); await storageRef.put(file) const url = await new Promise((resolve, reject) => { try { // pass resolve to subscribe. The subscribe will then call resolve with the url storageRef.getDownloadURL().subscribe(resolve) // you need to check if the callback to passed to subscribe // is guaranteed to be called, otherwise you need to // handle that case otherwise your code flow will // stuck at this situation } catch (err) { reject(err) } }) urlArray.push(url) } sub.filesUrls = urlArray; return this.finilize(sub); } finilize(sub: Submission) { //actually creates the submission let subRef = this.db.database.ref(`/submissions/${sub.medicUid}`).push(); let subKey = subRef.getKey(); sub.uid = subKey; return subRef.update(sub); }
  1. Si storageRef.put(file) hace algunas cosas de red y desea paralelizar eso (lo que no siempre es una buena idea), puede usar Promise.all y Array.map .
 async createSubmission(sub: Submission, files: Files[]): Promise { //first add files to storage and create the url array let urlArray: string[]; urlArray = Promise.all(files.map(async(file) => { const storageRef = this.storage.ref(`files/${file.name}`); await storageRef.put(file) const url = await new Promise((resolve, reject) => { try { // pass resolve to subscribe. The subscribe will then call resolve with the url storageRef.getDownloadURL().subscribe(resolve) // you need to check if the callback to passed to subscribe // is guaranteed to be called, otherwise you need to // handle that case otherwise your code flow will // stuck at this situation } catch (err) { reject(err) } }) return url })) sub.filesUrls = urlArray; return this.finilize(sub); } finilize(sub: Submission) { //actually creates the submission let subRef = this.db.database.ref(`/submissions/${sub.medicUid}`).push(); let subKey = subRef.getKey(); sub.uid = subKey; return subRef.update(sub); }

A medida que usa TypeScript, debe agregar la información de tipo correspondiente a mi código.

Además, debe verificar si storageRef.getDownloadURL() proporciona una API Promise y, de ser así, reemplace la new Promise y la subscribe con esa.

almost 3 years ago · Juan Pablo Isaza Denunciar

0

Creo que lo que estás buscando es "Promise.all ()"

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Promise.all resuelve una serie de Promesas.

En este ejemplo, urlArray contendrá los valores resueltos de getDownloadUrl

 let urlArrayTasks = []; for(let file of files){ urlArrayTasks.push(this.getDownloadURL(file)); } let urlArray = await Promise.all(urlArrayTasks);
almost 3 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda