2012-04-20 103 views
2

Is JavaScript guaranteed to be single-threaded? 它变得很清楚,但是javascript是单线程还有警告。取消ajax请求:处理程序仍然可以执行

我想知道下面的伪代码是否总是可以预测的(我“使用”的jQuery)

var lastReq; 
$('#button').click(function() 
{ 
    if (lastReq) lastReq.abort(); 
    lastReq = $.ajax(...); 
}); 

的情况下可能是click事件和中止,从服务器的数据之间通过并且在事件之前发生了一件事。如果这在中止之前发生,则会触发ajax帖子的成功事件。 我不知道如何真正测试这种可能的竞争条件。

有没有人有一个想法这是如何工作的?或者如何用一个准备好的例子来测试这个?

回答

1

编辑: 只要中止请求,浏览器就不应该再听它了。所以当它到达事件队列中的响应时,我的猜测是它应该抛出。


不过,如果您有任何关于它的问题,你可以尝试以下方法:

你能在你的成功的功能+网址取消本身,如果它检测到它不再需要做的检查运行?

举例来说(我不是说你应该这样来做,我没有尝试过任何连接到jqXHR要求):

var numReq = 0, lastReq; 

$('#button').on('click', function(e) { 
    if (lastReq) { lastReq.abort(); } 
    numReq ++; 
    lastReq = $.ajax({ 
     success : function(d, s, x) { 
      if (x.reqNum < numReq) { return; } 
     } 
    }); 
    lastReq.reqNum = numReq; 
}); 

我的理解是AJAX事件将不会被加入到事件队列,直到按钮点击后完成的,所以你不应该(理论上)担心阿贾克斯后设置reqNum ...


我也尝试下面的代码:

var numReq = 0, lastReq, timer = 100, 
    c = setInterval(function() { 
     if (lastReq) { lastReq.abort(); } 
     numReq ++; 
     lastReq = $.ajax({ 
      url  : 'index.html', 
      cache : false, 
      success : function(d, s, x) { 
       if (x.reqNum < numReq) { console.log('it happens'); } 
      } 
     }); 
     lastReq.reqNum = numReq; 
    }, timer); 

改变计时器以尝试匹配(尽可能接近)页面的加载时间。我没有“碰巧”出现。

1

我不知道,如果这种解决方法可能是真正有用的,并防弹(我想有创意),但是,因为jQuery的1.5 AJAX方法返回一个Deferred对象lastReq有可用state()方法

From http://api.jquery.com/deferred.state/

deferred.state()方法返回一个字符串,表示Deferred对象的当前状态。递延对象可以在三种状态之一:

...

“解决”:递延对象是在解决状态,这意味着无论是deferred.resolve()或deferred.resolveWith( )已被调用该对象并且doneCallbacks被称为(或正在调用的过程中)

,所以你可以重构你的代码,像这样

var lastReq; 
$('#button').click(function() { 
    if (lastReq) { 
     if (lastReq.state() === "resolved") { 
      return false; /* done() of the previous ajax call is in the process of 
           being called. Do nothing and wait until the state 
           is resolved */ 
     } 
     else { 
      lastReq.abort(); 
     } 
    } 

    lastReq = $.ajax(url).done(function() { 
      /* do something */ 
      lastReq = null; 
    }); 
}); 

希望能帮助给你的想法去努力,但我怀疑有没有真的需要这样的解决办法