критические разделы JavaScript или проблема семафора - PullRequest
3 голосов
/ 08 февраля 2010
function myobj(){
  var gup=this;
  this.lastindex=-1;
  this.criticalSectionInTimer=0;
  this.updateTimer;

  this.start = function(l){
      if((typeof this.updateTimer)=="number"){
        clearInterval ( this.updateTimer );
      }
      this.updateTimer=setInterval(function() {gup.getMessages();} , 30);
    }

    this.stop= function(){
      if((typeof this.updateTimer)=="number"){
        clearInterval ( this.updateTimer );
      }  
    }

  this.addUpdate(i){
    //some code
  }

  this.rrrrnr=0;

  this.getMessages = function (){
    if(this.criticalSection==0){
       this.criticalSection=1;
      this.rrrrnr++;
      console.log("in critical section"+this.rrrrnr);
         var url="getmessages.php?lastindex="+this.lastindex;
         $.getJSON(url,
             function(data){
              gup.lastindex=data.lastindex;
              $.each(data.updates, function(i,item){
                gup.addUpdate(item);
              });
           }
         );
       console.log("out critical section"+this.rrrrnr);
       this.criticalSection=0;
    }
  }

}

var m= new myobj();
myobj.start();

У меня есть код сверху. У меня есть основной цикл, который делает обновления в определенный промежуток времени. Проблема в том, что я понял, что он попадает в «критическую секцию», которую я разделил переменной this.criticalSection.

Из firebug я получаю сообщения "в критической секции" + индекс и "вне критической секции" + индекс в правильном порядке, но запрос ajax все еще обрабатывается. Но я получаю запрос с тем же индексом, и я действительно не знаю, где искать проблему.

Есть ли какие-либо встроенные функции для семафоров или критических секций в javascript?

Ответы [ 3 ]

1 голос
/ 09 июля 2013

Семафоров или критических секций нет, потому что JavaScript однопоточный. Вызов ajax является асинхронным, поэтому он запускает запрос, а затем с радостью продолжает работу и покидает ваш критический раздел. Как уже упоминалось, простое решение состоит в том, чтобы сделать запрос синхронным, но это противоречит цели ajax.

Глядя на свой код, кажется, что вы пытаетесь получать обновления через регулярные промежутки времени. Если это так, почему бы не запланировать следующее обновление в обратном вызове запроса ajax?

this.getMessages = function (){
    var url="getmessages.php?lastindex="+this.lastindex;
    $.getJSON(url,
        function(data){
            gup.lastindex=data.lastindex;
            $.each(data.updates, function(i,item){
                gup.addUpdate(item);
            });
  gup.updateTimer=setTimeout(gup.getMessages, 30);
        }
    );

}

Это устранит необходимость в семафорах и больше соответствует управляемой событиями природе JavaScript. Недостатком является то, что обновления не выполняются с точными интервалами. Кроме того, 30 миллисекунд кажется чрезвычайно коротким интервалом.

0 голосов
/ 08 февраля 2010

Проблема довольно проста.

Вы используете AJAX, который по определению является асинхронным. Это означает, что вы выполняете $ .getJSON, и js продолжит работу и выйдет из критической секции во время обработки запроса. Поэтому несколько вызовов getMessages могут быть выполнены до того, как завершатся первые запросы.

Кажется, вы намереваетесь, чтобы такой вызов getJSON НЕ был асинхронным и был заблокирован в критическом разделе до его завершения. Для этого необходимо установить для свойства async значение false, что-то в строках:

$.ajax({
  dataType: 'json',
  url:  "getmessages.php?lastindex="+this.lastindex,
  type: 'GET',
  async: false,
  success: function(data){
      gup.lastindex=data.lastindex;
      $.each(data.updates, function(i,item){
          gup.addUpdate(item);
      });
});
0 голосов
/ 08 февраля 2010

jQuery отправляет AJAX Async по умолчанию.Старайтесь делать getJSON try:

$.ajax({
  dataType: 'json',
  url:  url,
  type: 'GET',
  async: false,
  success: function(data){
              gup.lastindex=data.lastindex;
              $.each(data.updates, function(i,item){
                gup.addUpdate(item);
              });
});
...