2

В Is JavaScript guaranteed to be single-threaded? становится ясно, что, хотя javascript является одиночным, все еще существуют предостережения.Отмена запроса ajax: может ли выполняться обработчик

мне было интересно ли следующий псевдокод всегда предсказуем (я «с помощью» JQuery)

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

Дело может быть, что между событием щелчка и прерыванием, данные с сервера пришли и положили событие на eventqueue. Если это произойдет непосредственно перед прерыванием, будет инициировано событие succes сообщения ajax. Я понятия не имею, как реально проверить это возможное состояние гонки.

Есть ли у кого-нибудь идеи, как это работает? Или как проверить это с помощью подготовленного примера?

ответ

1

Редактировать: Как только вы отмените запрос, браузер больше не должен его прослушивать. Поэтому, когда он достигает ответа в очереди событий, я предполагаю, что он должен просто выбросить его.


Однако, если у вас возникли проблемы с ним, вы можете попробовать следующее:

Не могли бы вы сделать проверку в функции успеха + 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; 
}); 

Мое понимание является Аякса событие не будет добавлена ​​в очередь событий, пока после нажатия кнопки будет сделано, так что вы не должны (теоретически) придется беспокоиться о настройке 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 Аякса вернуть отложенный объект lastReq есть state() доступного метод

От http://api.jquery.com/deferred.state/

Метод deferred.state() возвращает строку, представляющую текущее состояние объекта Отложенное. Отложенный объект может находиться в одном из трех состояний:

...

«решен»: Отложенный объект находится в разрешенном состоянии, а это означает, что либо 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; 
    }); 
}); 

надеюсь, что это может помочь, чтобы дать вам представление о том, чтобы работать, но я подозреваю, что нет действительно нуждается в такого рода обходной путь