取消 ajax 请求:处理程序是否仍可执行

Canceling an ajax request: can the handler still be executed

本文关键字:是否 可执行 程序 处理 ajax 请求 取消      更新时间:2023-09-26

In JavaScript 能保证是单线程的吗?很明显,无论JavaScript是单线程的,仍然需要注意。

想知道以下伪代码是否总是可预测的(我正在"使用"jQuery)

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

情况可能是在单击事件和中止之间,来自服务器的数据通过并将事件放在 de eventqueue 上。如果这种情况发生在中止之前,将触发 ajax 帖子的成功事件。我不知道如何真正测试这种可能的竞争条件。

有谁知道这是如何工作的?或者如何用准备好的示例来测试这一点?

我不知道

这种解决方法是否真的有用并且是防弹的(我试图发挥创造力),但是,由于 jQuery 1.5 ajax 方法返回一个延迟对象,lastReq state()可用的方法

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

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

"solved":延迟对象处于已解决状态,这意味着已为对象调用了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; 
     });
});

希望这可以帮助您找到一个工作的想法,但我怀疑实际上并不需要这种解决方法

编辑:一旦您中止请求,浏览器就不应该再侦听它了。因此,当它到达事件队列中的响应时,我的猜测是它应该将其丢弃。


但是,如果您遇到问题,可以尝试以下操作:

如果检测到它不再需要运行,您能否检查您的成功函数 + url 以自行取消?

例如(我并不是说你应该这样做,我还没有尝试将任何东西附加到 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 事件不会添加到事件队列中,因此您(理论上)不必担心在 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);

改变计时器以尝试匹配(尽可能接近)页面的加载时间。我没有出现"它发生"。