Estoy clasificando una matriz grande y quiero actualizar la interfaz de usuario en mi aplicación web mientras se ejecuta la sort . En mi función de comparación personalizada, actualizo el contenido HTML cada 10 000 (más o menos) comparaciones, pero el navegador no refleja estos cambios.
large_array.sort( (a,b) => { ++comparisons if( comparisons % 10000 == 0 ) { // this works: console.log(comparisons) // this doesn't: document.querySelector('#sort-progress').textContent = comparisons } return custom_sort(a,b) })Lo que encontré es que usar trabajadores web debería ser la solución "correcta", pero eso significaría rediseñar completamente la aplicación. Así que espero encontrar alguna solución.
Su enfoque actual no funciona porque el código JavaScript se ejecuta en el subproceso principal de la interfaz de usuario y lo vincula hasta que se completa la sort , por lo que el navegador no puede actualizar la visualización de la página hasta que finaliza la sort y el código JavaScript termina de ejecutarse. permitiendo que el bucle de eventos se complete.
Algunas opciones vienen a la mente:
Use un trabajador web (como indicó).
Ordene la matriz en fragmentos, retrocediendo para permitir que el navegador vuelva a pintar antes de activar la clasificación del siguiente fragmento con setTimeout(..., 0) o similar. No ceda con demasiada frecuencia o terminará tardando una eternidad en ordenar el resultado, pero de vez en cuando debería ser bueno.
async , ocasionalmente (por ejemplo, aproximadamente cada 10,000 elementos) que permite que el navegador realice actualizaciones de visualización al await delay(0) donde delay es un envoltorio para setTimeout .Lo que encontré es que usar trabajadores web debería ser la solución "correcta", pero eso significaría rediseñar completamente la aplicación.
Eso dependerá mucho de lo que estés clasificando. Si está clasificando algo transferible o que se puede serializar con el algoritmo de clonación estructurada , no debería ser necesario rediseñar completamente la aplicación solo para esto. Necesitas:
postMessage la matriz al trabajador ( transferir si es posible).
Haga que el trabajador envíe actualizaciones sobre su progreso que usted usa para actualizar la interfaz de usuario.
Haga que el trabajador postMessage un mensaje en la matriz ordenada de vuelta a su código.
Pero si lo que está en la matriz no se puede manejar de esa manera, habrá más trabajo involucrado. Por ejemplo, podrías:
Cree una nueva matriz que contenga solo la información necesaria para ordenar, junto con el índice original de cada objeto de la matriz.
postMessage esa matriz al trabajador web.
Haga que el trabajador envíe actualizaciones sobre su progreso que usted usa para actualizar la interfaz de usuario.
Haga que el trabajador postMessage un mensaje en la matriz ordenada de vuelta a su código.
Recorra la matriz recibida colocando los elementos en el lugar en el que deben ir (por ejemplo, realizando operaciones de intercambio) o construyendo una nueva matriz con los elementos en el orden en que deben ir.
Sin embargo, dicho esto, implementar Timsort como una función async con pausas periódicas puede ser más simple.