Question

J'ai une application web où il y a une minuterie qui compte en permanence vers le bas. Pendant ce temps, le client vérifie fréquemment avec le serveur pour voir si plus de temps a été ajouté à la minuterie. Le code ressemble à ceci:

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;
};

Il est, bien sûr, un peu plus complexe que cela, mais vous pouvez voir la condition de la race inhérente. Que faire si la mise à jour et la fonction de la tique sont tous deux tentent de modifier time en même temps?

Franchement, je ne sais pas javascript assez pour comprendre comment faire face à ce genre de problème de concurrence: est-il un moyen facile de faire, ou sinon, quelqu'un peut me diriger vers des ressources où je peux en apprendre davantage?

Merci.

Était-ce utile?

La solution

Vous ne disposez pas d'une condition de course, parce que Javascript n'exécute pas en même temps.

Chaque fois qu'un rappel est tiré d'une opération asynchrone (AJAX, setTimeout, etc.), ce rappel doit se terminer avant d'exécuter un autre rappel d'une autre opération asynchrone peut être appelé. Donc, si update() est en cours d'exécution, aucun autre Javascript est. Une fois que se termine update(), d'autres opérations de callbacks async peuvent être tirées (par exemple, tick()). Il est intéressant, c'est aussi pourquoi setTimeout et son acabit ne sont pas garantis pour exécuter au moment précis le délai d'attente est atteinte:. un autre javascript peuvent bloquer l'exécution du rappel

Consultez http://ejohn.org/blog/how-javascript-timers -travail / pour quelques bonnes informations sur la façon dont tout cela fonctionne.

Autres conseils

Javascript est seul thread. Il n'y a pas de condition de course. Il n'y a aucun moyen de javascript pour les deux lignes time = newtime; et time -= 1; à se chevaucher pendant l'exécution. En fait, les deux fonctions sont garanties ne se chevauchent pas. L'un d'eux se déroulera et l'autre se déroulera.

Je me trompais: cela ne résout pas le problème! (Après le code explaination)

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;
};

Le problème avec cette mauvaise solution est que faire de cette façon que vous déplacez simplement la question de la condition de course de time variable NEWTIME variable.

Il suffit de penser ceci: l'exécution de tick atteint et exécute la ligne time = NEWTIME; maintenant, avant de continuer, la mise à jour s'appelé et NEWTIME obtient une X valeur. Maintenant, l'exécution tique continue d'exécuter NEWTIME = false;. De cette façon, vous avez perdu la valeur de X NEWTIME et ainsi l'effet d'une mise à jour () appelez-nous!

Le problème a besoin de quelques sémaphores. Je le fais beaucoup pour l'envoi ajax après une précédente se termine. Votre cas est semblable un peu;)

Essayez quelque chose comme ça. Il doit ignorer toutes les tentatives pour diminuer la valeur du temps qui entrent en collision avec rappel ajax.

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

Une autre chose - le setTimeout fonctionne comme un nouveau thread et j'attendre à ce que les navigateurs font l'accès mem synchronisation, de sorte qu'il pourrait être suffisant pour vérifier si la valeur n'a pas augmenté avant décrémentation. Mais la solution ci-dessus est plus souple et sûr.

Et une petite astuce - éviter l'interrogation avec AJAX trop souvent - il peut causer des problèmes supplémentaires - comme les demandes qui reviennent dans un ordre différent que envoyé, et utilisation de la mémoire de Firefox construire un beaucoup trop de ajax une minute;)

Tant que vous ajoutez quelques secondes pour vous heure actuelle, vous devriez être bien.

Au lieu de faire time = newtime; essayer time += newtime; cette façon, vous ne perdrez pas la seconde où vous êtes inquiet au sujet.

, vous êtes toujours seulement de perdre une seconde au pire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top