2011-08-03 11 views
14

Tengo un código que debe ejecutarse después de un retraso de 5000 ms.Actualmente estoy usando setTimeout pero es asincrónico y quiero que la ejecución espere su devolución. He intentado usar la siguiente:Retraso sincrónico en la ejecución del código

function pauseComp(ms) 
{ 
    var curr = new Date().getTime(); 
    ms += curr; 
    while (curr < ms) { 
     curr = new Date().getTime(); 
    } 
} 

Pero el código quiero retrasar está llegando algunos objetos usando raphaeljs y la pantalla no es en absoluto fácil. Estoy tratando de usar el plugin doTimeout. Necesito tener un retraso solo una vez, ya que la demora y el código que se retrasará están en un bucle. No necesito un ID, así que no lo estoy usando. Por ejemplo:

for(i; i<5; i++){ $.doTimeout(5000,function(){ 
     alert('hi'); return false;}, true);} 

Esta espera a 5 seg acaben dando primeras iteraciones de bucle Hi y luego sucesivas muestran alerta inmediatamente después de la primera. Lo que quiero que haga es esperar 5 segundos, dar alerta nuevamente, esperar y luego dar alerta, y así sucesivamente.

Cualquier sugerencia/sugerencias son apreciadas!

Respuesta

2

JavaScript es un lenguaje de subproceso único. No puede combinar setTimeout y procesamiento síncrono. Lo que sucederá es que el cronómetro caducará, pero luego el motor JS esperará para procesar los resultados hasta que se complete el guión actual.

Si desea métodos sincrónicos, ¡simplemente llame al método directamente!

Si desea procesar algo después del setTimeout, inclúyalo o llámelo desde la función de tiempo de espera.

3

Los bucles sin tiempo de espera (que controlan el tiempo o cuentan hasta 1000000 o lo que sea) solo bloquean el navegador. setTimeout (o el complemento $.doTimeout) es la mejor manera de hacerlo.

La creación de tiempos de espera dentro de un bucle no funcionará porque el bucle no espera a que ocurra el tiempo de espera anterior antes de continuar, como ha descubierto. Probar algo de la misma familia:

// Generic function to execute a callback a given number 
// of times with a given delay between each execution 
function timeoutLoop(fn, reps, delay) { 
    if (reps > 0) 
    setTimeout(function() { 
       fn(); 
       timeoutLoop(fn, reps-1, delay); 
       }, delay); 
} 

// pass your function as callback 
timeoutLoop(function() { alert("Hi"); }, 
      5, 
      5000); 

(acabo adoquinadas esto junto con rapidez, por lo que aunque estoy seguro de que funciona se podría mejorar de varias maneras, por ejemplo, en el "bucle" que podría pasar un índice valor en la función de devolución de llamada para que su propio código sepa qué iteración está haciendo. Pero con suerte lo pondrá en marcha.)

+0

Junto a setTimeout es una mejor opción, la solicitud OP un método síncrono @ThinkBonobo respondió correctamente – robsonrosa

+1

@robsonrosa -. El PO también dijo que" el código quiero retrasar está llegando algunos objetos que usan raphaeljs y la pantalla no es para nada uniforme. "No puede usar código síncrono * y * dibujar cosas, porque la pantalla no se volverá a pintar hasta que se complete el código síncrono. El hecho de que el OP haya pedido algo no lo hace hacerlo posible. – nnnnnn

20

Variación en la respuesta aceptada que es tan buena como esta.

Además, estoy de acuerdo con las advertencias de preferir setTimeout y la función asincrónica llamando pero a veces, por ejemplo, en la construcción de pruebas, sólo tiene un comando síncrono espera ...

function wait(ms) { 
    var start = Date.now(), 
     now = start; 
    while (now - start < ms) { 
     now = Date.now(); 
    } 
} 

si quieres que en cuestión de segundos, dividir inicio ms por 1000 mientras compruebo ...

+2

Debe ser la respuesta aceptada. – robsonrosa

0

He creado una función de tiempo de espera síncrono simple. Funciona de dos formas diferentes, devolución de llamada y no devolución de llamada.

función:

function wait(ms, cb) { 
    var waitDateOne = new Date(); 
    while ((new Date()) - waitDateOne <= ms) { 
    //Nothing 
    } 
    if (cb) { 
    eval(cb); 
    } 
} 

ejemplo de devolución de llamada:

wait(5000,"doSomething();"); 

ejemplo no devolución de llamada:

console.log("Instant!"); 
wait(5000); 
console.log("5 second delay"); 
+1

Use 'cb()' en lugar de 'eval (db)'. secuencia de comandos en una cadena no es una buena práctica. Uso: 'wait (5000, function() {console.log (" test! ")})'. Por cierto, es mejor usar setTimeout si necesita devolución de llamada – Soaku

0

Así es como se puede utilizar el plugin de jQuery doTimeout

jQuery('selector').doTimeout([ id, ] delay, callback [, arg ... ]); 

Desde el docs: "Si la devolución de llamada devuelve true, el bucledoTimeoutejecutará de nuevo, después del retraso, creando un bucle de sondeo hasta que la devolución de llamada devuelve un valor que no sea cierto. "

var start = Date.now(); 
 
console.log("start: ", Date.now() - start); 
 
var i = 0; 
 
$.doTimeout('myLoop', 5000, function() { 
 
    console.log(i+1, Date.now() - start); 
 
    ++i; 
 
    return i == 5 ? false : true; 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-dotimeout/1.0/jquery.ba-dotimeout.min.js"></script>

Cuestiones relacionadas