【问题标题】:javascript critical sections or semaphore problemjavascript 临界区或信号量问题
【发布时间】:2010-02-08 19:25:36
【问题描述】:
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 分隔的“关键部分”。

从萤火虫我得到消息“在关键部分”+索引和“在关键部分”+索引以正确的顺序,但ajax请求仍在处理中。但是我收到了具有相同索引的请求,我真的不知道在哪里寻找问题。

javascript 中是否有任何用于信号量或临界区的内置功能?

【问题讨论】:

    标签: javascript ajax jquery semaphore


    【解决方案1】:

    没有信号量或临界区,因为 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 毫秒似乎是一个极短的时间间隔。

    【讨论】:

      【解决方案2】:

      jQuery 默认发送 AJAX 异步。尝试做getJSON:

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

      【讨论】:

      • 使用同步 ajax 调用通常是一个糟糕的选择。 UI 完全锁定并在请求期间显示为冻结状态。
      • @Jonathon 我发现 UI 锁定有同样的问题;(
      【解决方案3】:

      问题很简单。

      您正在使用 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);
            });
      });
      

      【讨论】:

      • 使用同步 ajax 调用通常是一个糟糕的选择。 UI 完全锁定并在请求期间显示为冻结状态。
      猜你喜欢
      • 2018-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多