webentwicklung-frage-antwort-db.com.de

Synchrone Verzögerung bei der Codeausführung

Ich habe einen Code, der nach einiger Verzögerung ausgeführt werden muss, sagen wir 5000 ms. Zur Zeit verwende ich setTimeout, aber es ist asynchron und ich möchte, dass die Ausführung auf ihre Rückkehr wartet. Ich habe folgendes versucht:

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

Der Code, den ich verzögern möchte, ist das Zeichnen einiger Objekte mit Raffaeljs, und die Anzeige ist überhaupt nicht glatt. Ich versuche das doTimeout-Plugin zu verwenden. Ich muss nur einmal eine Verzögerung haben, da sich die Verzögerung und der zu verzögernde Code beide in einer Schleife befinden. Ich benötige keine ID, also benutze ich sie nicht.

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

Dies wartet 5 Sekunden, bevor zuerst Hi und dann aufeinanderfolgende Wiederholungen der Schleifenwiederholung unmittelbar nach dem ersten angezeigt werden. Ich möchte, dass es 5 Sekunden dauert, um den Alarm erneut zu warten, dann den Alarm zu geben und so weiter. 

Irgendwelche Hinweise/Vorschläge sind dankbar!

22
kavita

Variation der akzeptierten Antwort, die genauso gut ist wie diese.

Ich stimme auch mit den Einschränkungen des Vorzugs von setTimeout und des asynchronen Funktionsaufrufs überein, aber manchmal benötigen Sie zum Erstellen von Tests nur einen synchronen Wartebefehl ...

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

wenn Sie es in Sekunden wünschen, teilen Sie den Start ms durch 1000 bei der while-Überprüfung ...

41
ThinkBonobo

JavaScript ist eine Singlethread-Sprache. Sie können setTimeout nicht mit synchroner Verarbeitung kombinieren. Was passiert, ist, dass der Timer abgelaufen ist, aber die JS-Engine wartet dann mit der Verarbeitung der Ergebnisse, bis das aktuelle Skript abgeschlossen ist.

Wenn Sie synchrone Methoden wünschen, rufen Sie die Methode einfach direkt auf!

Wenn Sie nach dem setTimeout etwas bearbeiten möchten, schließen Sie es ein oder rufen Sie es über die Timeout-Funktion auf.

5
OverZealous

Ich habe eine einfache synchrone Timeout-Funktion erstellt. Es funktioniert auf zwei verschiedene Arten, Rückruf und Nichtrückruf.

funktion:

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

rückrufbeispiel:

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

nicht-Rückrufbeispiel:

console.log("Instant!");
wait(5000);
console.log("5 second delay");
2
andrew65952

Nicht-Timeout-Schleifen (die die Zeit prüfen oder auf 1000000 zählen oder was auch immer), blockieren den Browser einfach. setTimeout (oder das $.doTimeout-Plugin) ist der beste Weg, dies zu tun.

Das Erstellen von Zeitüberschreitungen innerhalb einer Schleife funktioniert nicht, da die Schleife nicht auf das vorherige Zeitlimit wartet, bevor Sie fortfahren, wie Sie festgestellt haben. Versuchen Sie etwas ähnlicheres:

// 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);

(Ich habe dies nur schnell zusammengeschustert, obwohl ich zuversichtlich bin, dass es funktioniert, könnte es auf verschiedene Weise verbessert werden, z. B. könnte es innerhalb der "Schleife" einen Indexwert an die Rückruffunktion übergeben, sodass der eigene Code weiß, welche Iteration verwendet wird Es ist bis zu. Aber hoffentlich werden Sie anfangen.)

2
nnnnnn

Wenn Sie die neue Asynchron/Erwartungs-Syntax nutzen möchten, können Sie das festgelegte Timeout in ein Versprechen umwandeln und dann darauf warten.

function wait(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("Done waiting");
      resolve(ms)
    }, ms )
  })
}  

(async function Main() {
  console.log("Starting...")
  await wait(5000);
  console.log("Ended!")
})();
2

So können Sie das JQuery-Plugin doTimeout verwenden

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

Von docs : "Wenn der Callback true zurückgibt, wird die SchleifedoTimeoutnach der Verzögerung erneut ausgeführt und erstellt eine Abfrageschleife, bis der Callback einen nicht-echten Wert zurückgibt.

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>

0
user2314737