2009-11-21 18 views
23

Supongamos que hago¿Los tiempos de espera iguales se ejecutan en orden en Javascript?

setTimeout(foo, 0); 

... 

setTimeout(bar, 0); 

¿Puedo estar seguro foo empezará a ejecutarse antes de la barra? ¿Qué pasa si en lugar de 0 utilizo un tiempo de espera de 1, 10 o 100 para la barra?

Experimentos simples muestran que en el caso de valores de tiempo de espera igual, los objetivos de tiempo de espera se ejecutan en el mismo orden que los mismos setTimeouts, pero ¿es seguro confiar en este comportamiento?

+0

Si usted se preocupa por el orden de ejecución , es posible que desee echar un vistazo a esta página http://www.onsip.com/blog/2012/06/29/avoiding-javascript-settimeout-and-setinterval-problems –

Respuesta

4

En resumen, no confíe en ello. Eche un vistazo al this.

Hay una gran cantidad de información en este figura de digerir pero entender que por completo le dará una mejor comprensión de cómo asíncrono funciona ejecución de JavaScript.

+7

No veo nada en ese artículo que es estrictamente en el punto. La pregunta no es sobre cuándo se ejecutan las funciones objetivo, sino sobre el orden en que se ejecutan. – jkl

+1

No cuente con un orden estricto, ese es el punto de "asincrónico" en el artículo antes mencionado. – jldupont

+4

Claro, los retrasos reales pueden ser más largos de lo esperado, y los intervalos funcionan de manera diferente a los temporizadores, pero el artículo no aborda la pregunta directamente. Independientemente de si se requieren 0 milisegundos o 100 años para ejecutar 'foo', ¿siempre ocurrirá antes de' bar'? ¿O el navegador puede elegir arbitrariamente? Siento que tiene que haber un estándar (o al menos algo de información) sobre esto. – Calvin

1

Hay un cierto mínimo que la demora realmente puede ser, y eso depende en gran medida del sistema operativo, el navegador, la actividad del navegador y la carga de la computadora. Tiendo a no ir por debajo de los 20 ms ya que creo que cualquier cosa menos que eso no hace ninguna diferencia.

Cuando pones dos retrasos que son iguales, no necesariamente significa que ocurrirá en ese orden.

Si desea asegurarse de que se llevará a cabo con el fin que tienden a hacer algo como esto:

setTimeout(function() { 
    foo(); 
    setTimeout(bar, 20) 
}, 20); 

Esto siempre será garantizar el orden.

Si está utilizando Firefox, para asegurarse de que su javascript sea en realidad multiproceso, puede consultar WebWorker, que es compatible con los navegadores más nuevos, pero no con IE.

+2

¿Conoces algún ejemplo específico en el que se ejecuten tiempos de espera iguales fuera de servicio? – jkl

+0

Simplemente no confío dependiendo de eso, cuando importa, ya que no he visto nada que lo garantice. –

+1

El retraso útil "más corto" dependerá de la implementación y la velocidad de la computadora, pero "0" es un tiempo útil para usar para setTimeout, ya que difiere la invocación hasta que se borre la pila de llamadas actual. – Nosredna

13

Leo el código fuente de Firefox, y al menos para ese navegador, hay una garantía de secuencia para los tiempos de espera que se especifican en orden no decreciente. De lo contrario, todas las apuestas están apagadas.

Específicamente, si en un contexto de ejecución dado establece un tiempo de espera para n, y luego uno para m, donde n < = m, los objetivos se ejecutarán en el orden en que se establecieron los tiempos de espera.

Pero no confíe en mi palabra. Creo que la implementación de la ventana está en nsGlobalWindow.cpp, y el método que realmente decide dónde se encuentran los tiempos de espera en la cola de ejecución se llama InsertTimeoutIntoList. Parece que el método atraviesa la cola hacia atrás buscando el primer tiempo de espera que es menor o igual que el tiempo de espera dado, e inserta el tiempo de espera dado después de él.

Por supuesto, cuando se establece el tiempo de espera, la hora actual del reloj se agrega al valor de tiempo de espera. Esta es la razón por la cual los valores de tiempo de espera deben estar en orden no decreciente para que los objetivos se ejecuten en secuencia.

13

No es seguro confiar en este comportamiento. Escribí un script de prueba que programa una serie de funciones (y a su vez también programan una serie de funciones) usando setTimeout (..., 0) y el orden en el que se llamaban las funciones no era siempre el mismo que el orden en que setTimeout se llamó (al menos en Chrome 11, que utilicé para ejecutar el script).

Puede ver/ejecutar la secuencia de comandos aquí: http://jsfiddle.net/se9Jn/ (la secuencia de comandos usa YUI para compatibilidad entre navegadores, pero Y.later usa setTimeout internamente).

Tenga en cuenta que si solo ejecuta el script y mira la consola, probablemente no verá un pedido ofensivo. Pero si inicia la secuencia de comandos, cambia a otra pestaña, carga algunas páginas y regresa a la página de prueba, debería ver errores en las devoluciones de llamadas en la consola.

Si necesita un ordenamiento garantizada, yo recomendaría la programación de la siguiente función al final de la función anterior:

setTimeout(foo, 0); 

... 

function foo() { 

    ... 

    setTimeout(bar, 0); 
} 
3

la respuesta es: No, orden de ejecución no está garantizada. Ocasionalmente he visto pedidos no FIFO en Chrome 40, especialmente si hago una pausa en el depurador mientras los tiempos de espera están pendientes. También tuve un avistamiento raro en la naturaleza: era la única explicación plausible de un incidente que investigué.

Si usted necesita orden de ejecución garantizada, en lugar de setTimeout(callback, 0) se puede hacer esto:

var queue = []; 
function handleQueue() { 
    queue.shift()(); 
} 
function queueCallback(callback) { 
    queue.push(callback); 
    setTimeout(handleQueue, 0); 
} 

Ahora, por garantizada foo, bar fin puede:

queueCallback(foo); 
... 
queueCallback(bar); 
Cuestiones relacionadas