working not loop ejemplo cleartimeout javascript settimeout

not - sleep javascript



Funciones de llamada con setTimeout() (5)

Simplemente pon...

por que

setTimeout(''playNote(''+currentaudio.id+'', ''+noteTime+'')'', delay);

funcionan perfectamente, llamando a la función después de la demora especificada, pero

setTimeout(playNote(currentaudio.id,noteTime), delay);

llama a la función playNote todo al mismo tiempo?

(estos setTimeout () s están en un bucle for)

o, si mi explicación es demasiado difícil de leer, ¿cuál es la diferencia entre las dos funciones?


Debido a que el segundo le dice que llame a la función playNote primero y luego pase el valor de retorno a setTimeout.


El primer formulario que lista funciona, ya que evaluará una cadena al final de la delay . Usar eval() generalmente no es una buena idea, así que debes evitar esto.

El segundo método no funciona, ya que inmediatamente ejecuta un objeto de función con el operador de llamada de función () . Lo que termina sucediendo es que playNote se ejecuta inmediatamente si usa el formulario playNote(...) , por lo que no sucederá nada al final de la demora.

En su lugar, debe pasar una función anónima a setTimeout, por lo que la forma correcta es:

setTimeout(function() { playNote(currentaudio.id,noteTime) }, delay);

Tenga en cuenta que está pasando setTimeout toda una expresión de función, por lo que se mantendrá en la función anónima y solo la ejecutará al final de la demora.

También puede pasar una referencia a setTimeout , ya que una referencia no se ejecuta inmediatamente, pero luego no puede pasar argumentos:

setTimeout(playNote, delay);

Nota:

Para eventos repetidos, puede usar setInterval() y puede establecer setInterval() en una variable y usar la variable para detener el intervalo con clearInterval() .

Usted dice que usa setTimeout() en un ciclo for . En muchas situaciones, es mejor usar setTimeout() en una función recursiva. Esto se debe a que en un ciclo for , las variables utilizadas en setTimeout() no serán las variables tal como eran cuando se setTimeout() , sino las variables tal como están después de la demora cuando se dispara la función.

Solo use una función recursiva para eludir todo este problema.

Uso de recursión para lidiar con tiempos de demora variables:

// Set original delay var delay = 500; // Call the function for the first time, to begin the recursion. playNote(xxx, yyy); // The recursive function function playNote(theId, theTime) { // Do whatever has to be done // ... // Have the function call itself again after a delay, if necessary // you can modify the arguments that you use here. As an // example I add 20 to theTime each time. You can also modify // the delay. I add 1/2 a second to the delay each time as an example. // You can use a condition to continue or stop the recursion delay += 500; if (condition) { setTimeout(function() { playNote(theID, theTime + 20) }, delay); } }


Literalmente creé una cuenta en este sitio para comentar la respuesta de Peter Ajtai (actualmente la más votada), solo para descubrir que necesitas 50 repeticiones (lo que sea que sea) para comentar, así que lo haré como respuesta, ya que probablemente valga la pena señalarlo un par de cosas.

En su respuesta, él declara lo siguiente:

También puede pasar una referencia a setTimeout , ya que una referencia no se ejecuta inmediatamente, pero luego no puede pasar argumentos:

setTimeout(playNote, delay);

Esto no es verdad Después de darle a setTimeout una referencia de función y una cantidad de retardo, los argumentos adicionales se analizan como argumentos para la función a la que se hace referencia. Lo siguiente sería mejor que envolver una llamada de función en una función.

setTimeout(playNote, delay, currentaudio.id, noteTime)

Siempre consulte los documentos.

Dicho esto, como señala Peter, una función recursiva sería una buena idea si quieres variar el retraso entre cada playNote() , o considerar usar setInterval() si quieres que exista la misma demora entre cada playNote() .

También vale la pena señalar que si desea analizar el i de su bucle for en un setTimeout() , debe setTimeout() en una función, como se detalla here.


No use string-timeouts. Es efectivo un eval , que es una cosa mala. Funciona porque está convirtiendo currentaudio.id y noteTime en las representaciones de cadena de sí mismo y escondiéndolo en el código. Esto solo funciona mientras esos valores tengan toString() s que generen una sintaxis literal de JavaScript que recreará el valor, que es verdadero para Number pero no para mucho más.

setTimeout(playNote(currentaudio.id, noteTime), delay);

eso es una llamada a la función. playNote se llama inmediatamente y el resultado devuelto de la función (probablemente undefined ) se pasa a setTimeout() , no a lo que desea.

Como mencionan otras respuestas, puede usar una expresión de función en línea con un cierre para hacer referencia a currentaudio y noteTime :

setTimeout(function() { playNote(currentaudio.id, noteTime); }, delay);

Sin embargo, si está en un bucle y currentaudio o noteTime es diferente cada vez que pasa el bucle, tiene el problema Closure Loop: se hará referencia a la misma variable en cada tiempo de espera, por lo tanto, cuando se llamen, obtendrá el mismo valor cada vez, el valor que quedó en la variable cuando el ciclo finalizó antes.

Puede solucionar esto con otro cierre, tomando una copia del valor de la variable para cada iteración del ciclo:

setTimeout(function() { return function(currentaudio, noteTime) { playNote(currentaudio.id, noteTime); }; }(currentaudio, noteTime), delay);

pero esto se está poniendo feo ahora. Mejor es la Function#bind , que aplicará parcialmente una función para usted:

setTimeout(playNote.bind(window, currentaudio.id, noteTime), delay);

( window es para establecer el valor de this dentro de la función, que es una característica de bind() que no necesita aquí).

Sin embargo, esta es una característica de ECMAScript Fifth Edition que no todos los navegadores admiten todavía. Entonces, si quiere usarlo primero tiene que hackear el soporte, por ejemplo:

// Make ECMA262-5 Function#bind work on older browsers // if (!(''bind'' in Function.prototype)) { Function.prototype.bind= function(owner) { var that= this; if (arguments.length<=1) { return function() { return that.apply(owner, arguments); }; } else { var args= Array.prototype.slice.call(arguments, 1); return function() { return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments))); }; } }; }


Prueba esto.

setTimeout(function() { playNote(currentaudio.id,noteTime) }, delay);