Espere 5 segundos antes de ejecutar la siguiente línea.

313

Esta función a continuación no funciona como yo quiero; siendo un novato de JS no puedo entender por qué.

Necesito que espere 5 segundos antes de verificar si newStatees así -1.

Actualmente, no espera, solo verifica de inmediato.

function stateChange(newState) {
  setTimeout('', 5000);

  if(newState == -1) {
    alert('VIDEO HAS STOPPED');
  }
}
copo de nieve
fuente
1
Posible duplicado de la secuencia
Anónimo

Respuestas:

323

Debe poner su código en la función de devolución de llamada que proporciona a setTimeout:

function stateChange(newState) {
    setTimeout(function () {
        if (newState == -1) {
            alert('VIDEO HAS STOPPED');
        }
    }, 5000);
}

Cualquier otro código se ejecutará de inmediato.

Joseph Silber
fuente
44
El problema principal es que en algunos casos (específicamente pruebas) esto es lamentablemente inadecuado. ¿Qué sucede si necesita dormir 500 ms antes de regresar de la función, por ejemplo, para simular una solicitud http asíncrona lenta ?
A.Grandt
14
Si por "prueba" te refieres a pruebas unitarias: tu marco de prueba debería tener una forma de ejecutar pruebas asíncronas. Si te refieres a las pruebas manuales: la pestaña Red de Chrome tiene un menú desplegable de limitación para simular solicitudes lentas.
Joseph Silber
1
¿Qué pasa si desarrollo una extensión de Chrome y el último valor evaluado en el script inyectado debería darme el resultado? y necesito algunos retrasos?
mirek
184

Realmente no debería estar haciendo esto , el uso correcto del tiempo de espera es la herramienta adecuada para el problema del OP y cualquier otra ocasión en la que solo desee ejecutar algo después de un período de tiempo. Joseph Silber lo ha demostrado bien en su respuesta. Sin embargo, si en algún caso de no producción realmente desea colgar el hilo principal por un período de tiempo, esto lo hará.

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}

Con ejecución en forma:

console.log('before');
wait(7000);  //7 seconds in milliseconds
console.log('after');

Llegué aquí porque estaba creando un caso de prueba simple para secuenciar una combinación de operaciones asincrónicas alrededor de operaciones de bloqueo de larga duración (es decir, manipulación costosa del DOM) y esta es mi operación de bloqueo simulada. Se adapta bien a ese trabajo, así que pensé que lo publicaría para cualquier otra persona que llegue aquí con un caso de uso similar. Aun así, está creando un objeto Date () en un ciclo while, lo que podría abrumar al GC si se ejecuta el tiempo suficiente. Pero no puedo enfatizar lo suficiente, esto solo es adecuado para pruebas, para construir cualquier funcionalidad real, debe consultar la respuesta de Joseph Silber.

Micrófono
fuente
77
Esto no detendrá la ejecución de JavaScript.
Terry Lin
23
@TerryLin Intenta ejecutarlo.
Mic
66
Así que básicamente estás perdiendo el tiempo de la CPU. Eso no es una espera, ya que no está poniendo el hilo en modo de suspensión permitiendo que el procesador principal se concentre en otras tareas.
Kyordhel
66
@Gzork Thread sleep es solo una forma de implementar una función de espera, y desafortunadamente no está disponible en el contexto de javascript del lado del cliente. Sin embargo, si está pensando que otras tareas asincrónicas en el cliente se completarán mientras se está ejecutando, entonces obviamente no lo ha probado. Aunque lo usaría en el hilo principal, armé un violín que ilustra cómo, incluso si se llama a través de setTimeout en primer lugar, todavía interrumpe otros eventos asíncronos jsfiddle.net/souv51v3/1 : encontrará incluso el La propia ventana JSFiddle deja de responder mientras se completa.
Mic
1
Solución horrible en mi humilde opinión: acapara la CPU mientras está "durmiendo". La forma correcta de dormir es a través de async / await ala this answer stackoverflow.com/questions/951021/… o Etienne's.
David Simic
163

Aquí hay una solución usando la nueva sintaxis async / await .

Asegúrese de verificar el soporte del navegador ya que esta es una nueva característica introducida con ECMAScript 6.

Función de utilidad:

const delay = ms => new Promise(res => setTimeout(res, ms));

Uso:

const yourFunction = async () => {
  await delay(5000);
  console.log("Waited 5s");

  await delay(5000);
  console.log("Waited an additional 5s");
};

La ventaja de este enfoque es que hace que su código se vea y se comporte como un código síncrono.

Etienne Martin
fuente
No necesita ECMAScript 6: si ya está utilizando promesas para realizar la carga asincrónica y solo desea imitar una parte de la cadena que lleva mucho tiempo, puede agregar esta función wait () a la cadena.
Dovev Hefetz
2
Esta es realmente la mejor respuesta con la nueva sintaxis. Tuve problemas con el uso de la solución wait () anterior.
pianoman102
36

No deberías solo intentar pausar 5 segundos en javascript. No funciona de esa manera. Puede programar una función de código para que se ejecute en 5 segundos a partir de ahora, pero debe poner el código que desea ejecutar más adelante en una función y el resto de su código después de esa función continuará ejecutándose inmediatamente.

Por ejemplo:

function stateChange(newState) {
    setTimeout(function(){
        if(newState == -1){alert('VIDEO HAS STOPPED');}
    }, 5000);
}

Pero, si tienes un código como este:

stateChange(-1);
console.log("Hello");

La console.log()declaración se ejecutará de inmediato. No esperará hasta que se active el tiempo de espera en la stateChange()función. No puede simplemente pausar la ejecución de JavaScript durante un período de tiempo predeterminado.

En cambio, cualquier código que desee ejecutar retrasos debe estar dentro de la setTimeout()función de devolución de llamada (o invocado desde esa función).

Si intentó "pausar" haciendo un bucle, esencialmente "colgaría" el intérprete de Javascript por un período de tiempo. Debido a que Javascript ejecuta su código en un solo subproceso, cuando realiza un bucle, no se puede ejecutar nada más (no se puede llamar a otros controladores de eventos). Por lo tanto, el bucle en espera de que cambie alguna variable nunca funcionará porque no se puede ejecutar ningún otro código para cambiar esa variable.

jfriend00
fuente
31
No puede simplemente pausar la ejecución de JavaScript durante un período de tiempo predeterminado . Creo que quieres decir que no deberías, ya que puedes (si quieres ahorcarte):var t = new Date().getTime(); while (new Date().getTime() < t + millisecondsToLockupBrowser);
Joseph Silber el
99
@JosephSilber: está bien, podría hacerlo, pero en la práctica eso no funciona, ya que muchos navegadores mostrarán un cuadro de diálogo que dice que un script no responde Y es una experiencia horrible para el usuario y es malo para la duración de la batería y la página está colgado mientras lo hacía y ... Eso sería malo.
jfriend00
12
Bien por supuesto, eso sería horrible, y nadie jamás debería hacer eso. Simplemente no pude resistir mi "bien en realidad" interior . Lo siento.
Joseph Silber
31

Si está en una función asíncrona , simplemente puede hacerlo en una línea:

console.log(1);
await new Promise(resolve => setTimeout(resolve, 3000)); // 3 sec
console.log(2);

Tenga en cuenta que si el objetivo es NodeJS, será más eficiente usar esto (es una función setTimeout predefinida y prometida):

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec
Shl
fuente
¿Cuál es la diferencia entre las dos implementaciones?
EAzevedo
1
Actualmente, no hay diferencia. Pero si en algún momento el nodo decidiera hacerlo más rápido / seguro / más eficiente, usará la versión del nodo js por adelantado. Aunque es más probable que la legibilidad sea el factor clave para la mayoría de las personas, en cuyo caso será mejor que use la primera forma.
Shl
Gracias. Su respuesta resolvió un problema que he estado enfrentando durante tres días. Gracias.
EAzevedo
8

Prueba esto:

//the code will execute in 1 3 5 7 9 seconds later
function exec() {
    for(var i=0;i<5;i++) {
        setTimeout(function() {
            console.log(new Date());   //It's you code
        },(i+i+1)*1000);
    }
}
Steve Jiang
fuente
7

La mejor manera de crear una función como esta para esperar en milisegundos, esta función esperará milisegundos proporcionados en el argumento:

function waitSeconds(iMilliSeconds) {
    var counter= 0
        , start = new Date().getTime()
        , end = 0;
    while (counter < iMilliSeconds) {
        end = new Date().getTime();
        counter = end - start;
    }
}

Jitendra Pal - JP
fuente
3

Según la respuesta de Joseph Silber , lo haría así, un poco más genérico.

Tendría su función (creemos una basada en la pregunta):

function videoStopped(newState){
   if (newState == -1) {
       alert('VIDEO HAS STOPPED');
   }
}

Y podría tener una función de espera:

function wait(milliseconds, foo, arg){
    setTimeout(function () {
        foo(arg); // will be executed after the specified time
    }, milliseconds);
}

Al final tendrías:

wait(5000, videoStopped, newState);

Esa es una solución, preferiría no usar argumentos en la función de espera (tener solo en foo();lugar de foo(arg);), pero eso es por ejemplo.

Sylhare
fuente
3

Esta solución proviene de la documentación de React Native para un control de actualización :

function wait(timeout) {
    return new Promise(resolve => {
        setTimeout(resolve, timeout);
    });
}

Para aplicar esto a la pregunta del OP, puede usar esta función en coordinación con await:

await wait(5000);
if (newState == -1) {
    alert('Done');
}
bearacuda13
fuente
1

Puede agregar demora haciendo pequeños cambios en su función (asíncrono y espera).

const add5SecondsDelay = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('5 seconds');
    }, 50000);
  });
}

async function asyncFunctionCall() {

  console.log("stpe-1"); 
  const result = await add5SecondsDelay ();
  console.log("step-2 after 5 seconds delay"); 

}

asyncFunctionCall();
p.durga shankar
fuente
-2

usando angularjs:

$timeout(function(){
if(yourvariable===-1){
doSomeThingAfter5Seconds();
}
},5000)
Dr. Abbos
fuente
-2

Crear nueva función Js

function sleep(delay) {
        var start = new Date().getTime();
        while (new Date().getTime() < start + delay);
      }

Llame a la función cuando desee retrasar la ejecución. Use milisegundos en int para el valor de retraso.

####Some code
 sleep(1000);
####Next line
Madushanka Sampath
fuente
3
Eso consumirá demasiados recursos.
awavi
-2

Lo usé para ejecutar juegos de PC desde edge o IE. Y se cierra automáticamente IE Edge después de 7 segundos.

Firefox y Google Chrome no se pueden usar para iniciar juegos de esta manera.

<html<body>
<a href="E:\game\game.exe" name="game" onmouseout="waitclose(7000);"> game
<img src="game.jpg" width="100%" height="97%" ></a>
<script>
function waitclose(ms){
 var start = new Date().getTime();var end=start;
 while(end < start + ms) {end = new Date().getTime();}
window.open('', '_self', ''); window.close();
}
</script>
</body></html>
usuario4565320
fuente