2012-06-28 7 views
6

El contexto¿Cómo lidiar con el proceso de carga pesada de los datos que se muestran en el navegador

  • Tenemos una aplicación basada en Ember que maneja gran cantidad de datos estructurados (modelos de procesos de negocio).
  • ¡Importante! Realmente nos gustaría mantener nuestra aplicación fuera de línea, en la medida de lo posible.

La necesidad

Aunque sólo tenemos que mostrar estos datos, editarlos, y así sucesivamente, no hay show-tapón en el radar ...

Pero ahora, desea aplicar el procesamiento en estos modelos: comprobación de validez, búsqueda de rutas ... y varios tipos de algoritmos que consumen tiempo/memoria.

El problema

hemos podido procesar algoritmos en el servidor, pero que mataría a modo fuera de línea de la aplicación.

Hemos pensado en los trabajadores de la web para evitar la congelación de aplicaciones y algoritmos de proceso en segundo plano, pero nos enfrentamos a un problema importante: la duplicación de datos al pasar los datos al trabajador. El uso de objetos transferibles haría que la aplicación pierda la propiedad (y los datos) durante al menos el cálculo, por lo que no parece viable.

¿Cómo manejarías este problema? ¿Es nuestra única salida el uso de una implementación de nuestros algoritmos "similar a una corito"? ¿Cualquier pista?

+0

Creo que la pregunta importante es si puede permitirse el lujo de no congelar la aplicación. Supongamos que el usuario realiza cambios en los datos mientras el algoritmo se está ejecutando. ¿Serán válidos/relevantes los resultados del proceso que se ejecuta en segundo plano? De lo contrario, probablemente sea mejor mostrar al usuario una barra de progreso y continuar con los cálculos. – Qnan

+0

¿Cuál es el problema con la duplicación de datos? ¿Demasiadas cosas para serializar al trabajador? –

+0

@SimoneGianni El problema principal es la sincronización de datos entre el contexto de UI y el contexto del trabajador –

Respuesta

3

Si su mayor preocupación es no congelar la IU durante el largo proceso de javascript que desarrolló, puede refactorizar los cuerpos de bucle en pasos secuenciales, de modo que cada paso llame al siguiente usando window.setTimeout. Esta técnica permite que el (único) hilo para procesar eventos de interfaz de usuario entre cada interacción:

var pr = function(x) {console.log(x)}; 
var COUNT=3; 

// original regular javascript loop 
for(var i=0; i<COUNT; i++) { 
    var msg = "current index is (" + i + ")"; 
    pr(msg); 
} 

// step-by-step sequential calls 
var body = function(i) { 
    var msg = "non-blocking for: index is (" + i + ")"; 
    pr(msg); 
} 
nonBlockingFor(body, 4); 

La función nonBlockingFor llama al primer argumento (como una función) el número de veces que pasa como segundo argumento. Es definición sigue:

// function constructor 
var nonBlockingFor = (function() { 
    function _run(context) { 
    if(context.idx > context.max) return; 
    context.fnc(context.idx++); 
    window.setTimeout((function(){ _run(context)}), 1); 
    } 
    return (function _start(ufn, uqt, runId) { 
    _run({idx: 0, max: uqt -1, fnc: ufn || (function(){}), runId: runId}); 
    }); 
})(); 

Tenga en cuenta que esta es una función muy simplificado y se puede mejorar para manejar otros multi-hilo de las cuestiones relacionadas - es decir: a la espera de los hilos para terminar (se unen). Espero que este código te ayude. Por favor, hágamelo saber si le gusta este enfoque al problema, podría pasar algún tiempo mejorando mi sugerencia, si lo desea.

+0

Muchas gracias por esta respuesta. De hecho, eso está muy cerca de lo que llamé un enfoque 'similar a la corotina' ... El problema con este tipo de solución es la complejidad general de la implementación en explosión cuando el algoritmo tiende a ser complejo. :-( –

+1

Lo bueno es que, después de configurar la biblioteca para que ejecute JavaScript no bloqueante/concurrente, puede desarrollar la biblioteca de negocios de una manera homogénea y directa. Por cierto, tal vez ya lo sepa, pero esto la biblioteca parece un buen candidato [https://github.com/caolan/async/]. –

+0

Gracias por el enlace. No conocía esta versión. Suena interesante. –

2

el tiempo ha pasado mucho tiempo, pero aún así: una solución puede ser http://jscex.info/

, JavaScript es un único subproceso en la naturaleza, y es una opción de diseño causa multihilo es un tema difícil el 99% de los desarrolladores de JavaScript casuales no se maneja adecuadamente .

Los trabajadores son la única forma de obtener otro hilo y no bloquear la IU, pero para hacerlos utilizables sin los efectos secundarios peligrosos del multihilo real, se ejecutan en un contexto completamente separado, como habrán notado. Por lo tanto, son más similares a llamar a un comando externo que pasa parámetros de línea de comando que a generar otro hilo.

Por lo tanto, trabajar en el modo "asíncrono" es la única solución en este momento, pero como no está esperando que se complete un clic de un botón o una conexión remota, el único evento asíncrono al que puede vincularse es el siguiente un temporizador, que conduce al estilo de código pobre que plaga las operaciones de larga ejecución en js.

Sin embargo, hay una pequeña biblioteca, que me pareció muy interesante y bastante desconocida, que (a pesar de su sitio web deficiente) puede "convertir" sobre la marcha un código de procedimiento bellamente escrito para el desorden de temporizadores y funciones el modelo asíncrono requiere intrínsecamente: http://jscex.info/

Como en Windows 3.1, solo necesita "ceder" ($ await (Jscex.Async.sleep (50));) algún tiempo al navegador para que no se congele por completo . En realidad, se congelará bajo el capó, pero si cedes con la suficiente frecuencia, nadie se dará cuenta :) (después de eso, así es como funciona la multitarea dentro de cada núcleo de tu CPU, muy pequeñas porciones de tiempo durante las cuales la CPU es 100%) trabajando en un solo conjunto de instrucciones ... lleva eso a 20 ms y nadie puede decirlo).

Creo que podría ayudarlo a "producir" un JS tipo Coroutine sin realmente "escribir" dicho código, sino delegando en un "precompilador" el trabajo de desordenarlo.

Cuestiones relacionadas