JavaScript - Loader mientras hace un forEach

 
Vista:
sin imagen de perfil

Loader mientras hace un forEach

Publicado por Quamis (3 intervenciones) el 07/02/2023 13:36:12
Buenas chic@s, estaba haciendo el típico spinner animado de "procesando..." mientras sube en bloque varios ficheros al servidor y guarda los registros correspondientes en base de datos, y no consigo hacer que se muestre un spinner durante ese proceso.
Estoy programando con javascript vanilla. Cada fichero que sube es un fetch a un php que procesa la subida.

El código es este, por cada fichero del array ficheros, ejecuta la funcion insertarRegistro y le pasa el tipo).
1
ficheros.forEach(insertarRegistro, tipo);

Esto lo hace bien. insertarRegistro hace un fetch por cada fichero. Lo que quiero es que se muestre el spinner durante todo el proceso, es decir, hasta que acabe el forEach:

1
2
3
4
5
6
7
8
// se muestra el loader
let loader = document.getElementById('loader-'+tipo);
loader.style.display = 'block';
 
ficheros.forEach(insertarRegistro, tipo);
 
// se oculta el loader.
loader.style.display = 'none';

Ayuda, por favor, he probado de varias maneras y nada. Gracias por adelantado.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 40
Ha mantenido su posición en JavaScript (en relación al último mes)
Gráfica de JavaScript

Loader mientras hace un forEach

Publicado por Marlon (90 intervenciones) el 07/02/2023 22:27:07
El problema es que la linea para ocultar el spinner se ejecuta inmediatamente después de iniciar el forEach, por lo que no espera a que se terminen las peticiones fetch. Para solucionarlo, puedes esperar a que se completen todas las peticiones antes de ocultar el spinner. Una forma de hacerlo es usando un Promise.all().

Puedes probar lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
let promises = ficheros.map(fichero => insertarRegistro(fichero, tipo));
 
// se muestra el loader
let loader = document.getElementById('loader-'+tipo);
loader.style.display = 'block';
 
Promise.all(promises)
  .then(() => {
    // se oculta el loader
    loader.style.display = 'none';
  });

Esto lo que hace es esperar a que todas las peticiones se procesen y cuando termine oculta el loader o muestra un error
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

Loader mientras hace un forEach

Publicado por Quamis (3 intervenciones) el 08/02/2023 08:40:28
Buenas Marlon, gracias por responder. He probado tu solución con el Promise.all, pero tampoco me funciona. El loader se pone en "block" un microsegundo y automaticamente en display none, mientras siguen subiendo las imágenes. No espera a que acabe todo lo que hace el loop.
Por si sirve para arrojar más luz al problema, copio aquí la función que ejecuta ese loop para cada fichero procesado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function insertarRegistro(fichero, tipo){
    // Validación del formato
    let valido = validarFicheros(fichero, tipo);
    if (valido){
        let url = new URL(route('admin.extras.create'));
        let formData = new FormData();
        formData.append('fichero', fichero, fichero.name);
        formData.append('tipo', tipo);
        let opciones = {
            method: 'POST',
            body: formData
        };
 
        fetch(url, opciones)
            .then((respuesta) => respuesta.json())
            .then((datos) => {
                if (datos.status == 'KO'){
                    datos.errores.forEach(error => {
                        mostrarError(error, tipo);
                    });
                }else{
                    vistaPreviaImagenes(datos);
                }
            }).catch(function (err) {
            console.warn('Algo salió mal: ', err);
        });
    }
}

Quizás haya que tocar algo ahí, el fetch sube los ficheros al server y mete el registro en la BD, y en el then del fetch crea la miniatura del fichero correspondiente con js.

Ayuda por favor. Muchas gracias por adelantado y por la paciencia.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Loader mientras hace un forEach

Publicado por Quamis (3 intervenciones) el 08/02/2023 09:57:12
Vale, esto también puede servir de pista. He hecho trazas de cada proceso, y el Promises all está funcionando para los fetch, pero no para el then de los fetchs, que es el que crea las miniaturas. Mira, estos son los logs en orden de ejecución:

mi_multiuploader.js:183 subiendo GAIA.png
mi_multiuploader.js:183 subiendo ba5bd8da92b070a62d7ec8229cde05af0cb8d0ab313f00d91beab8c8adc7fe89._RI_V_TTW_.jpg
mi_multiuploader.js:183 subiendo manticora - sorceress.jpg
mi_multiuploader.js:183 subiendo 9F108T9UDC2JCubvaPSPJF1ebkZ.jpg
mi_multiuploader.js:183 subiendo comp.png
mi_multiuploader.js:374 fin de promesas
mi_multiuploader.js:232 creando vista previa de 1675846510961595.webp
mi_multiuploader.js:232 creando vista previa de 1675846511440165.webp
mi_multiuploader.js:232 creando vista previa de 1675846512249750.webp
mi_multiuploader.js:232 creando vista previa de 1675846513853908.webp
mi_multiuploader.js:232 creando vista previa de 1675846514767412.webp
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar