Frage

ich eine Web-Anwendung, in der es einen Timer, der ständig nach unten zählt. Inzwischen hat der Kunde häufig überprüft mit dem Server zu sehen, wenn mehr Zeit, um den Timer hinzugefügt wurde. Der Code sieht etwa so aus:

function tick() {
    // This function is called once every second
    time -= 1;
    redisplay(time);
};
function update(newtime) {
    // This function is called whenever the ajax request
    // to the server yields a new time
    time = newtime;
};

Es ist, natürlich, ein wenig komplexer als das, aber man kann die inhärente Race-Bedingung sehen. Was passiert, wenn das Update und die Zecke Funktion sind beide time gleichzeitig zu ändern versuchen?

Ehrlich gesagt, ich weiß es nicht annähernd genug, um Javascript zu verstehen, wie mit dieser Art von Gleichzeitigkeit Thema befassen: Gibt es eine einfache Möglichkeit, dies zu tun, oder wenn nicht, kann jemand Punkt mich auf Ressourcen, wo ich mehr lernen kann?

Danke.

War es hilfreich?

Lösung

Sie haben nicht eine Race-Bedingung, weil Javascript nicht gleichzeitig ausgeführt werden.

Jedes Mal, wenn ein Rückruf von einer Asynchron-Operation ausgelöst wird (AJAX, setTimeout, usw.), muss dieser Rückruf vor einem anderen Rückruf von einem anderen asynchronen Betrieb Ausführung beenden kann aufgerufen werden. Also, wenn update() läuft, ist kein anderer Javascript. Sobald update() abgeschlossen ist, können andere Rückrufe von Asynchron-Operationen ausgelöst werden (zB tick()). Interessanterweise ist diese auch deshalb setTimeout und seine Konsorten nicht das Timeout in dem Augenblick zur Ausführung garantiert erreicht ist. Einige andere JavaScript, um den Rückrufs Hinrichtung blockiert sein könnten

Schauen Sie sich http://ejohn.org/blog/how-javascript-timers -Arbeit / für ein paar gute Informationen darüber, wie all dies funktioniert.

Andere Tipps

ist Javascript single threaded. Es gibt keine Race-Bedingung. Es gibt keine Möglichkeit in Javascript für die beiden Linien time = newtime; und time -= 1; zu Überschneidungen bei der Ausführung. In der Tat sind die beiden Funktionen garantiert nicht zu überlappen. Einer von ihnen laufen und dann in die andere laufen.

Ich war falsch: dies das Problem nicht lösen! (Explaination nach dem Code)

NEWTIME = false;
function tick() {
    // This function is called once every second
    if (NEWTIME) {
        time = NEWTIME;
        NEWTIME = false;
    }
    time -= 1;
    redisplay(time);
};
function update(newtime) {
    // This function is called whenever the ajax request
    // to the server yields a new time
    NEWTIME = newtime;
};

Das Problem mit dieser falschen Lösung besteht darin, dass auf diese Weise tun Sie gerade die Race-Bedingung Ausgabe von variablen time auf variable NEWTIME bewegen.

Man denke nur an das: die Ausführung von tick erreicht und führt die Linie time = NEWTIME; jetzt, bevor Sie fortfahren, zu aktualisieren aufgerufen und NEWTIME erhält einen Wert X. Jetzt tick Ausführung fortgesetzt Ausführung NEWTIME = false;. Auf diese Weise können die X Wert von NEWTIME verloren haben und so die Wirkung eines Updates () -Aufruf!

Das Problem braucht einige Semaphore. Ich tun, dass viel für Ajax nach vorherigen Ausführungen zu senden. Ihr Fall ist ein wenig gleich;)

Versuchen Sie so etwas. Es sollte alle Versuche Abnahmedauer, dass kollidieren mit AJAX Callback ignorieren.

window.TimeKeeper = new function(){
this.time=0; //initial value, whatever
this.isopen=true;

this.decrement = function(){ 
 if(this.isopen){
  this.time--;
  redisplay(this.time);
  }
 }
this.set = function(val){
 if(this.isopen){
  this.isopen=false;
  this.time=val;
  this.isopen=true;
  } else {
  //another AJAX callback is modifying time. 
   //You can enqueue current value and put it later
  }
 }

}

function tick() {
    TimeKeeper.decrement();

};
function update(newtime) {
    TimeKeeper.set(newtime);
};

Eine weitere Sache - die setTimeout funktioniert wie ein neuer Thread, und ich würde erwarten, dass Browser die Synchronisierungs mem Zugang zu tun, so dass es genug sein könnte, um zu überprüfen, ob der Wert nicht wuchs nicht vor seinem Erniedrigen. Aber die obige Lösung ist flexibler und sicherer.

Und ein kleiner Tipp - avoid anfragende mit AJAX zu oft - es zusätzliche Probleme verursachen kann - wie Anfragen kommen wieder in einer anderen Reihenfolge als abgeschickt, und Firefox Speicherverbrauch viel zu viel Ajax Minute Aufbau;)

Solange Sie noch einige Sekunden, um Ihnen aktuelle Zeit hinzufügen Sie sollten in Ordnung sein.

Statt time = newtime; Versuch time += newtime; tun diese Weise werden Sie die zweite nicht verlieren Sie besorgt über.

Dennoch sind Sie nur eine Sekunde, im schlimmsten Fall zu verlieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top