2009-09-20 35 views
6

Escribo un plugin de ubicuidad. La devolución de llamada de función larga para una consulta ajax está bloqueando el subproceso de GUI que causa el bloqueo de Firefox.¿Hay una forma correcta de 'ceder' en el sentido de conexión cooperativa en javascript?

La solución obvia parece ser el uso de algún tipo de ejecución diferida de (es decir, queremos añadir periódicamente la llevar a cabo haciendo esta consulta función al final de la cola de eventos y luego permitir que otros comandos para llevar a cabo .

La única manera que puedo pensar de hacer esto es utilizar setTimeout con un tiempo de espera de cero ... es esto está garantizado para trabajar, o hay una mejor manera de hacer esto.

+0

¿Cómo te va el AJAX? Si está cargando una etiqueta de script, eso podría estar bloqueando (bloques de navegador hasta que vuelva la secuencia de comandos). –

+0

Estoy usando jQuery.get – user47741

Respuesta

7

Usando setTimeout con un tiempo de espera muy pequeño (0 o casi cero si se siente paranoico) es la única forma de hacerlo en el contexto de un navegador. funciona muy bien y es muy confiable, pero asegúrese de ceder con frecuencia pero no demasiado también, ya que tarda un tiempo en volver a usted ("un tiempo" en sentido informático, por supuesto; es casi instantáneo [modulo otras cosas que puede estar haciendo] en términos humanos).

+2

Todas las implementaciones modernas de navegador han fijado setTimeout a ~ 10ms (básicamente 10 ms en todos los sistemas que no son de Windows, donde la resolución del temporizador necesaria para obtener <16ms temporizadores tiene un impacto significativo en el uso de energía). Entonces, realmente no necesita preocuparse por acortar el tiempo de espera. – olliej

+1

@olliej: Esa es información obsoleta (si fue correcta en '09, pero tampoco fue mi experiencia). Los navegadores hacen un manejo mucho más sofisticado que eso, dependiendo del origen de la llamada 'setTimeout'. Esto fue [codificado hace un par de años en la especificación HTML5] (http://www.w3.org/TR/html5/webappapis.html#timer-initialization-steps) pero como ya he dicho, los vendedores ya estaban jugando (dispar) juegos antes de eso. Versión corta: si su código no fue llamado por un temporizador, puede usar 0, y los navegadores modernos obtendrán ** muy ** cerca de eso. –

3

Asegúrese de estar utilizando una solicitud asincrónica ya que una solicitud síncrona bloquea el navegador (lo que explicaría el bloqueo de la GUI).

Si este no es su problema, creo que desea algo así como esta cola de tareas.

var queue = []; 

queue.push(someTaskFunction); 
queue.push(anotherTaskFunction); 
// ... 

var runQueue = (function() { 
    var len = queue.length, task = 0; 
    for (; task < len; task++) { 
     yield queue[task](); 
    } 
}()); 

Llame al runQueue.next() para ejecutar la siguiente tarea. Envuélvalo en una declaración try..catch como tal:

try { 
    runQueue.next(); 
} catch (e if (e instanceof StopIteration)) {} 
+0

La llamada es asincrona – user47741

+0

Cool - No sabía que los generadores se habían agregado a javascript. ¿Estoy en lo cierto al entender que otras tareas pueden tomar un control cada vez que una función retorna? – user47741

+0

Tenga en cuenta que los generadores son relativamente nuevos en JavaScript y no necesariamente son ampliamente compatibles. –

Cuestiones relacionadas