Con el siguiente código, intento documentar el progreso de una serie de bucles.
Sin embargo, como verá, el progreso no se documenta sin problemas en el DOM. Se están saltando muchos incrementos porcentuales.
Cómo puedo arreglar eso ?
;(async () => { let width = document.getElementById('width') let numOfImages = 8 let images = Array.from(Array(numOfImages).keys()) let pixelsPerImage = 3600 let totalPixels = numOfImages * pixelsPerImage let currentLoop = 0 for (let img of images) { await new Promise((resolve) => { // this setTimeout is actually an image.onload callback setTimeout(() => { let i = 0 while (i < pixelsPerImage) { ;(function(cloop) { window.requestAnimationFrame(() => { let prcnt = ((100/totalPixels) * cloop).toFixed(2) width.innerHTML = prcnt + '%' width.style.width = prcnt + '%' }) })(++currentLoop) i++ } resolve() }, 5000) }) } await Promise.all(promises) })()Parece que está intentando ejecutar 8 promesas en paralelo, pero se ejecutan una tras otra.
Es así: se crean 8 promesas, una tras otra. cada promesa registra un setTimeout de 5000ms.
Una vez que terminen los 5000 ms, habrá 8 devoluciones de llamada en espera, el tiempo de ejecución las llamará una tras otra (JavaScript es de un solo subproceso).
La primera promesa hará un ciclo de 3600 y escribirá en el console.log 3600 veces. Luego, el tiempo de ejecución llamará a la próxima devolución de llamada de promesa, y el siguiente bucle 3600 hará lo mismo ... hasta que terminen los 8 bucles.
Ves muchos console.log porque lo haces 3600*8 veces... no ves los cambios de DOM porque el navegador se renderizará solo después de que se complete la ejecución.
Para ver los cambios de dom, tendrá que "liberar" la ejecución de su código, puede hacerlo con setTimeout(..., 0) para obtener el siguiente procesamiento inmediato. o incluso mejor, use requestAnimationFrame
Querrás hacer lo mínimo en cada cuadro para permitir que el navegador lo procese rápido. evitar grandes bucles, código lento.
Lo siguiente que probablemente encontrará es que la velocidad de progreso cambia de acuerdo con su CPU, si quiere ser el mismo sin importar la potencia de la CPU, querrá comenzar a tomar en cuenta el tiempo, que es un tema totalmente diferente :-)
Ralentiza el progreso general, ya que ahora estoy esperando que finalicen las actualizaciones de HTML antes de pasar al siguiente bucle, pero el progreso que se muestra en el HTML ahora es preciso y fluido. Es una compensación.
;(async () => { let width = document.getElementById('width') let topLoops = 8 let innerLoops = 3600 let totalLoops = topLoops * innerLoops let currentLoop = 0 let images = Array.from(Array(topLoops).keys()) for (let img of images) { await new Promise((resolve) => { // this setTimeout is actually an image.onload callback setTimeout(async() => { let i = 0 while (i < innerLoops) { currentLoop++ await new Promise((resolve) => { window.requestAnimationFrame(() => { let prcnt = ((100/totalLoops) * currentLoop).toFixed(2) width.innerHTML = prcnt + '%' width.style.width = prcnt + '%' resolve() }) }) i++ } resolve() }, 5000) }) } await Promise.all(promises) })() #width { float:left; height: 20px; background: red; color: black; padding: 3px; } <div id="width"></div>