2012-01-31 31 views
28

Muy a menudo vemos en las bibliotecas de código JavaScript como esto:llamada setTimeout sin demora

setTimeout(function() { 
    ... 
}, 0); 

me gustaría saber por qué utilizar un código de este tipo envoltura.

+5

** CONSEJO PRO: ** No necesita ', 0 'al final. – vsync

Respuesta

40

muy simplificada:

navegadores son solo roscado y este hilo único (el hilo UI) es compartida entre el motor de representación y el motor js.

Si lo que quiere hacer toma mucho tiempo (hablamos de ciclos aquí pero todavía) podría detener (paus) la renderización (flujo y pintura).

En los buscadores también existe "The bucket" donde todos los eventos se ponen por primera vez a la espera de que el hilo de la interfaz de usuario se haga con lo que sea que esté haciendo. Tan pronto como termina el hilo, mira en el cubo y elige la tarea primero en la fila.

Usando setTimeout crea una nueva tarea en el depósito después de la demora y deja que el hilo se ocupe de ella tan pronto como esté disponible para más trabajo.

Una historia:

después de 0 ms retardo crear una nueva tarea de la función y lo ponen en el cubo. En ese momento exacto, el hilo de la interfaz de usuario está ocupado haciendo otra cosa, y ya hay otras tareas en el contenedor . Después de 6ms, el hilo está disponible y obtiene la tarea enfrente de tuyo, bueno, eres el siguiente. ¿Pero que? ¡Eso fue una gran cosa! Tiene estado como foreeeeeever (30ms) !!

Por fin, ahora el hilo está hecho con eso y viene y obtiene su tarea .

La mayoría de los navegadores tienen un retraso mínimo que es más que 0, por lo que poner 0 como retraso significa: Ponga esta tarea en la cesta CUANTO ANTES. Pero decirle a la UA que lo ponga en el cubo lo antes posible no garantiza que se ejecutará en ese momento. El cubo es como la oficina de correos, podría ser que haya una larga cola de otras tareas. Las oficinas de correos también tienen una sola cadena con una sola persona que ayuda a toda la tarea ...lo siento clientes con sus tareas. Tu tarea debe ponerse en la línea como todos los demás.

Si el navegador no implementa su propio ticker, utiliza los ciclos de tic del sistema operativo. Los navegadores antiguos tenían retrasos mínimos entre 10-15 ms. HTML5 specifies que si la demora es menor a 4 ms, el AU debe aumentarla a 4ms. Se dice que es consistent across browsers released in 2010 and onward.

Ver How JavaScript Timers Work de John Resig para más detalles.

Editar: Véase también What the heck is the event loop anyway? por Philip Roberts de JSConf UE 2014. Esta es la visión obligatoria para todas las personas que tocan código de front-end.

1

Para permitir que se ejecuten los tiempos de espera establecidos previamente.

7

Hay un par de razones por las que haría esto

  • Hay una acción que no desea ejecutar de inmediato, pero no desea ejecutar en algún período de tiempo futuro próximo.
  • desea permitir que otras personas que manipulan previamente registrados desde un setTimeout o setInterval para ejecutar
3

Cuando se desea ejecutar resto de su código sin tener que esperar anterior para terminar es necesario agregar que en el método anónimo pasó a setTimeout función. De lo contrario el código anterior esperará hasta que se hace

Ejemplo:

function callMe() 
{ 
    for(var i = 0; i < 100000; i++) 
    { 
     document.title = i; 
    } 
} 

var x = 10; 
setTimeout(callMe, 0); 

var el = document.getElementById('test-id'); 
el.innerHTML = 'Im done before callMe method'; 

Esa es la razón por la que lo uso.

6

Aparte de las respuestas anteriores, me gustaría agregar otro escenario útil en el que pueda pensar: "escapar" de un bloque try-catch. Un setTimeout-delay desde dentro de un bloque try-catch se ejecutará fuera del bloque y cualquier excepción se propagará en el ámbito global.

Quizás el mejor escenario de ejemplo: en el JavaScript de hoy, con el uso más común de los denominados Deferreds/Promises para devoluciones de llamada asincrónicas, (a menudo) realmente se está ejecutando dentro de un try-catch. Deferreds/Promises envuelven la devolución de llamada en un try-catch para poder detectar y propagar una excepción como un error en la cadena asincrónica. Todo esto es bueno para las funciones que necesitan estar en la cadena, pero tarde o temprano estarás "hecho" (es decir, buscó todo tu ajax) y quieres ejecutar código no asíncrono simple donde no quieras que las excepciones sean " escondido "más. AFAIK Dojo, Q de Kris Kowal, MochiKit y Google Closure lib usan envoltura de try-catch (aunque no jQuery).

(En un par de ocasiones extrañas, también utilicé la técnica para reiniciar el código de estilo singleton sin causar recursión. Es decir, realizar un reinicio de recuperación en el mismo ciclo).

Cuestiones relacionadas