2011-11-19 50 views
15

Estoy tratando de ajustar mi cabeza alrededor de setTimeout, pero no puedo hacer que funcione correctamente.setTimeout retraso no funciona

He creado un ejemplo aquí: http://jsfiddle.net/timkl/Fca2n/

Quiero un texto la cuenta atrás después se hace clic en un ancla - pero mi setTimeout parece disparar en el mismo tiempo, a pesar de que he puesto el retraso a 1 segundo.

Esta es mi HTML:

<a href="#">Click me!</a> 

<span id="target"></span> 

Ésta es mis JS:

$(document).ready(function() { 


function foo(){ 

    writeNumber = $("#target"); 

    setTimeout(writeNumber.html("1"),1000); 
    setTimeout(writeNumber.html("2"),1000); 
    setTimeout(writeNumber.html("3"),1000); 
    }; 

$('a').click(function() { 
foo(); 
}); 

}); 

Cualquier pista sobre lo que podría estar haciendo mal es muy apreciada :)

Respuesta

37

setTimeout toma una función como argumento. Está ejecutando la función y pasando el resultado al setTimeout (por lo que la función se ejecuta de inmediato). Puede utilizar funciones anónimas, por ejemplo:

setTimeout(function() { 
    writeNumber.html("1"); 
}, 1000); 

Tenga en cuenta que el mismo se puede decir de setInterval.

+0

Thx por ayudarme! :) He actualizado mi jsfiddle: http://jsfiddle.net/timkl/cRDQh/ Todavía obtengo el mismo resultado, el setTimeouts se dispara al mismo tiempo. – timkl

+1

No hay problema :) Si no desea que se activen al mismo tiempo, cambie la duración del tiempo de espera. Por ejemplo, 1000ms para el primer tiempo de espera, 2000ms para el segundo y así sucesivamente. –

+0

Lo mismo es cierto no solo para 'setTimeout' y' setInterval', sino que para cada caso se supone que debe pasar la devolución de llamada como uno de los parámetros. – Tadeck

2

Es necesario utilizar una función referencia se invocará más tarde cuando expire el temporizador. Envuelva cada instrucción en una función anónima para que no se ejecute inmediatamente, sino cuando el temporizador expire.

setTimeout(function() { writeNumber.html("1"); },1000); 

Además, se desea utilizar un valor de retardo diferente para cada uno, para que los temporizadores no caducan al mismo tiempo. Vea un violín actualizado en http://jsfiddle.net/RqCqM/

1

Simplemente use setInterval(). Here es lo que se me ocurrió. Aquí está su nueva javascript:

function foo(){ 
    writeNumber = $("#target"); 
    number  = 0; 
    writeNumber.html(number); 
    setInterval(function(){ 
     number = number+1; 
     writeNumber.html(number); 
    },1000); 
    }; 
$('a').click(function() { 
foo(); 
}); 
5

Es necesario para envolver sus declaraciones en funciones anónimas y también escalonar los tiempos de su -

setTimeout(function(){writeNumber.html("1")},1000); 
setTimeout(function(){writeNumber.html("2")},2000); 
setTimeout(function(){writeNumber.html("3")},3000); 

Si establece todo para 1000 los pasos hará más o menos plazo al mismo tiempo como setTimeout función ejecutará la tarea 1 segundo después de llamar a la función, no 1 segundo después de finalizar la llamada anterior a la setTimeout función.

Demo - http://jsfiddle.net/JSe3H/1/

+0

+1 Buen punto: ha señalado no solo la forma en que se pasa la devolución de llamada, sino también cuándo se ejecuta. – Tadeck

1

Es necesario utilizar un tot funciones que se llamará después se pasa el tiempo de espera; usted puede usar la función anónima también, entonces su función foo se verá así:

function foo(){ 

writeNumber = $("#target"); 

setTimeout(function() { writeNumber.html("1"); },1000); 
setTimeout(function() { writeNumber.html("2"); },1000); 
setTimeout(function() { writeNumber.html("3"); },1000); 

}; 
0

Aterricé en esta pregunta. Se ha respondido adecuadamente, y creo que usar setInterval como @Purag sugirió es probablemente el mejor enfoque para obtener el comportamiento funcional deseado. Sin embargo, el ejemplo de código inicial no tuvo en cuenta el comportamiento asintomático de JavaScript. Este es un error que a menudo ocurre, en el que me he involucrado más que nunca :).

Así como una nota al margen que quería dar otra solución posible para este que imita el intento inicial, pero esta vez sí considera Asynchronousity de Javascript:

setTimeout(function() { 
    writeNumber.html("1"); 
    setTimeout(function() { 
     writeNumber.html("1"); 
     setTimeout(function() { 
      writeNumber.html("1"); 
     }, 1000); 
    }, 1000); 
}, 1000); 

Ahora por supuesto esto es claramente terribles código!

He dado un JSFiddle de trabajo en my own SO question. Este código ejemplifica la llamada pirámide de doom. Y esto puede mitigarse mediante el uso de promesas de JavaScript, como se muestra en las respuestas a mi pregunta. Se necesita algo de trabajo para escribir una versión de WriteNumber() que utiliza promesas, pero luego el código puede ser reescrita para somehting como:

2

Hay una disposición para pasar argumentos a la función. En su caso, usted puede hacerlo por

setTimeout(writeNumber.html,1000,1); 
setTimeout(writeNumber.html,1000,2); 
setTimeout(writeNumber.html,1000,3); 

tercer argumento de la función setTimeout se pasan a la función writeNumber.html