Ejecutar script después de un retraso específico usando JavaScript


189

¿Existe algún método de JavaScript similar al jQuery delay()o wait()(para retrasar la ejecución de un script por un período de tiempo específico)?

Respuestas:


189

Hay lo siguiente:

setTimeout(function, milliseconds);

función que se puede pasar el tiempo después del cual se ejecutará la función.

Ver: Método de ventanasetTimeout() .


3
No es una expresión que se ejecuta, es una función. La respuesta de @Marius lo ilustra.
pedrofurla

117
Esto no es un retraso, es un tenedor. El retraso debería funcionar en el mismo hilo.
DragonLord

13
Esto ejecutará inmediatamente function_reference. Para "trabajar" (asincrónicamente) se debe indicar como: setTimeout (function () {MethodToCall ();}, 1000);
Bernoulli IT

66
Quiero señalar que estamos hablando de JavaScript; sacar "hilos" o que debería funcionar "sincrónicamente" puede ser cierto técnica y semánticamente, pero no encaja realmente en el contexto de JavaScript, teniendo en cuenta que realmente no hay forma de lograr un retraso con ninguno de esos métodos (usted no ' t cree "hilos" en JS como lo hace en otros idiomas). Además, esto no se ejecutará inmediatamente a function_referencemenos que lo incluya (). Es decir, function_referenceeso es una referencia; pasar function_reference()invocaría la función de inmediato.
Danny Bullis

237

Solo para agregar a lo que todos los demás han dicho sobre setTimeout: si desea llamar a una función con un parámetro en el futuro, debe configurar algunas llamadas a funciones anónimas.

Debe pasar la función como argumento para que se llame más tarde. En efecto, esto significa sin corchetes detrás del nombre. Lo siguiente llamará a la alerta de inmediato y mostrará 'Hola mundo':

var a = "world";
setTimeout(alert("Hello " + a), 2000);

Para solucionar esto, puede poner el nombre de una función (como lo ha hecho Flubba) o puede usar una función anónima. Si necesita pasar un parámetro, debe usar una función anónima.

var a = "world";
setTimeout(function(){alert("Hello " + a)}, 2000);
a = "Stack Overflow";

Pero si ejecuta ese código, notará que después de 2 segundos la ventana emergente dirá 'Hola desbordamiento de pila'. Esto se debe a que el valor de la variable a ha cambiado en esos dos segundos. Para que diga 'Hola mundo' después de dos segundos, debe usar el siguiente fragmento de código:

function callback(a){
    return function(){
        alert("Hello " + a);
    }
}
var a = "world";
setTimeout(callback(a), 2000);
a = "Stack Overflow";

Esperará 2 segundos y luego emergerá 'Hola mundo'.


37

Solo para expandir un poco ... Puede ejecutar código directamente en la setTimeoutllamada, pero como dice @patrick , normalmente asigna una función de devolución de llamada, como esta. El tiempo es milisegundos

setTimeout(func, 4000);
function func() {
    alert('Do stuff here');
}

27

Si realmente desea tener una función de bloqueo (síncrona) delay(por cualquier motivo), ¿por qué no hacer algo como esto?

<script type="text/javascript">
    function delay(ms) {
        var cur_d = new Date();
        var cur_ticks = cur_d.getTime();
        var ms_passed = 0;
        while(ms_passed < ms) {
            var d = new Date();  // Possible memory leak?
            var ticks = d.getTime();
            ms_passed = ticks - cur_ticks;
            // d = null;  // Prevent memory leak?
        }
    }

    alert("2 sec delay")
    delay(2000);
    alert("done ... 500 ms delay")
    delay(500);
    alert("done");
</script>

2
La dificultad con esta solución es que utiliza activamente un procesador, lo que conduce a un mayor uso de energía y una disminución de los recursos disponibles para otros subprocesos / procesos (por ejemplo, otras pestañas, otros programas). La suspensión, por el contrario, suspende temporalmente el uso de un hilo de los recursos del sistema.
ramcdougal 01 de

1
mejor usar Date.now () en lugar de la nueva Date () y no pensar en pérdidas de memoria
WayFarer

1
Por supuesto, es un uso intensivo de la CPU, pero para pruebas rápidas y sucias funciona
Maris B.

Quiero una versión que no bloquee el hilo, para poder actualizar el DOM antes delayde responder (para responder a esta pregunta ). ¿Hay alguna manera de hacerlo?
Gui Imamura

3
Una rutina más compacta: función de retraso (ms) {var start_time = Date.now (); while (Date.now () - hora_inicio <ms); }
Duke

15

Debe usar setTimeout y pasarle una función de devolución de llamada. La razón por la que no puedes usar sleep en javascript es porque bloquearías que toda la página no hiciera nada mientras tanto. No es un buen plan. Usa el modelo de eventos de Javascript y mantente feliz. ¡No luches!


2
Aún así sería útil para fines de prueba. Como retrasar el envío de un formulario durante unos segundos para evaluar los cambios de página antes de que se realice una nueva solicitud HTTP.
rushinge

1
@rushinge luego configura la devolución de llamada para enviar el formulario y deshabilita el envío predeterminado del formulario
Populus

1
Mala idea dejar un enlace como código ... ya que ahora no funciona.
Emmet Arries

1
O sabes, podría arreglarlo.
Patrick

14

También puede usar window.setInterval () para ejecutar código repetidamente a intervalos regulares.


2
setInterval () no debería usarse en su lugar debería usar setTimeout
paul

9
setTimeout()lo hace una vez, lo setInterval()hace repetidamente. Si desea que su código se ejecute cada 5 segundos, setInterval()está hecho para el trabajo.
rcoup

11

Para agregar los comentarios anteriores, me gustaría decir lo siguiente:

La setTimeout()función en JavaScript no detiene la ejecución del script per se, sino que simplemente le dice al compilador que ejecute el código en algún momento en el futuro.

No hay una función que realmente pueda pausar la ejecución integrada en JavaScript. Sin embargo, puede escribir su propia función que haga algo así como un bucle incondicional hasta que se alcance el tiempo utilizando la Date()función y agregando el intervalo de tiempo que necesita.


11

Si solo necesita probar un retraso, puede usar esto:

function delay(ms) {
   ms += new Date().getTime();
   while (new Date() < ms){}
}

Y luego, si quieres retrasar 2 segundos, lo haces:

delay(2000);

Sin embargo, podría no ser el mejor para la producción. Más sobre eso en los comentarios


@ U2744 COPO DE NIEVE ¿Puedes intentar ser un poco más preciso en tu comentario
Christoffer

1
Bueno, es un circuito ocupado que agotará las baterías de las computadoras portátiles y otros dispositivos móviles, y probablemente también evite que la UI responda (o incluso se muestre).
Ry-

@ U2744SNOWFLAKE Tiene sentido. He actualizado la respuesta, para lo que utilicé esta función :)
Christoffer

2
Funciona lo suficientemente bien en desarrollo para una solución rápida y sucia (y temporal).
HumanInDisguise

5

¿Por qué no puedes poner el código detrás de una promesa? (escrito en la parte superior de mi cabeza)

new Promise(function(resolve, reject) {
  setTimeout(resolve, 2000);
}).then(function() {
  console.log('do whatever you wanted to hold off on');
});


5

La respuesta simple es:

setTimeout(
    function () {
        x = 1;
    }, 1000);

La función anterior espera 1 segundo (1000 ms) y luego establece x en 1. Obviamente, este es un ejemplo; Puedes hacer lo que quieras dentro de la función anónima.


4

Me gustó mucho la explicación de Maurius (la respuesta más votada) con los tres métodos diferentes para llamar setTimeout.

En mi código, deseo navegar automáticamente a la página anterior al completar un evento de guardar AJAX. La finalización del evento guardar tiene una ligera animación en el CSS que indica que el guardado fue exitoso.

En mi código encontré una diferencia entre los dos primeros ejemplos:

setTimeout(window.history.back(), 3000);

Este no espera el tiempo de espera: se llama a back () casi de inmediato, sin importar el número que ingrese para el retraso.

Sin embargo, cambiando esto a:

setTimeout(function() {window.history.back()}, 3000);

Esto hace exactamente lo que esperaba.

Esto no es específico de la operación back (), sucede lo mismo con alert(). Básicamente con el alert()utilizado en el primer caso, se ignora el tiempo de retraso. Cuando descarto la ventana emergente, la animación para el CSS continúa.

Por lo tanto, recomendaría el segundo o tercer método que describe, incluso si está utilizando funciones integradas y no está utilizando argumentos.


1

Tenía algunos comandos ajax que quería ejecutar con un retraso en el medio. Aquí hay un ejemplo simple de una forma de hacerlo. Sin embargo, estoy preparado para ser destrozado por mi enfoque poco convencional. :)

//  Show current seconds and milliseconds
//  (I know there are other ways, I was aiming for minimal code
//  and fixed width.)
function secs()
{
    var s = Date.now() + ""; s = s.substr(s.length - 5);
  return s.substr(0, 2) + "." + s.substr(2);
}

//  Log we're loading
console.log("Loading: " + secs());

//  Create a list of commands to execute
var cmds = 
[
    function() { console.log("A: " + secs()); },
    function() { console.log("B: " + secs()); },
    function() { console.log("C: " + secs()); },
    function() { console.log("D: " + secs()); },
    function() { console.log("E: " + secs()); },
  function() { console.log("done: " + secs()); }
];

//  Run each command with a second delay in between
var ms = 1000;
cmds.forEach(function(cmd, i)
{
    setTimeout(cmd, ms * i);
});

// Log we've loaded (probably logged before first command)
console.log("Loaded: " + secs());

Puede copiar el bloque de código y pegarlo en una ventana de consola y ver algo como:

Loading: 03.077
Loaded: 03.078
A: 03.079
B: 04.075
C: 05.075
D: 06.075
E: 07.076
done: 08.076

1

La solución más simple para llamar a su función con retraso es:

function executeWithDelay(anotherFunction) {
    setTimeout(anotherFunction, delayInMilliseconds);
}

0

función de retraso:

/**
 * delay or pause for some time
 * @param {number} t - time (ms)
 * @return {Promise<*>}
 */
const delay = async t => new Promise(resolve => setTimeout(resolve, t));

uso dentro de la asyncfunción:

await delay(1000);

-1

Como dijo otro, setTimeout es su apuesta más segura.
Pero a veces no puede separar la lógica de una nueva función, entonces puede usar Date.now () para obtener milisegundos y hacer el retraso usted mismo ...

function delay(milisecondDelay) {
   milisecondDelay += Date.now();
   while(Date.now() < milisecondDelay){}
}

alert('Ill be back in 5 sec after you click OK....');
delay(5000);
alert('# Im back # date:' +new Date());

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.