Возможно ли, что, используя jQuery, я отменить / прервать запрос Ajax, от которого я еще не получил ответ?
@LukeMadhanga; Я думаю, что ajaxStop обнаруживает, когда все запросы AJAX завершены, он не останавливает запрос. По моему опыту, вы могли бы использовать его так: $(document).ajaxStop(function(){alert("All done")}). Использование .abort() - лучший вариант.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы не можете отозвать запрос, но можете установить значение тайм-аута, по истечении которого ответ будет проигнорирован. См. Этот страница для параметров jquery AJAX. Я считаю, что ваш обратный вызов ошибки будет вызван, если период тайм-аута будет превышен. Для каждого запроса AJAX уже существует тайм-аут по умолчанию.
Вы также можете использовать метод прерывание () для объекта запроса, но, хотя он заставит клиента прекратить прослушивание события, май, вероятно, не остановит сервер от его обработки.
Это запрос асинхронный, то есть после отправки он уже там.
В случае, если ваш сервер запускает очень дорогостоящую операцию из-за запроса AJAX, лучшее, что вы можете сделать, - это открыть свой сервер для прослушивания запросов на отмену и отправить отдельный запрос AJAX, уведомляющий сервер о необходимости остановить все, что он делает.
В противном случае просто игнорируйте ответ AJAX.
В этом контексте асинхронность просто означает, что запрос не прерывает выполнение скрипта. Теперь у браузеров есть возможность преждевременно прервать запрос до его завершения.
Как мы можем отправить на сервер запрос на отмену? Я не понимаю, как сервер узнает, какой запрос прекратить обработку? Не могли бы вы привести пример? Спасибо.
@LuckySoni, Elephanthunter обсуждает только клиентскую сторону. Запрос .abort не повлияет на сервер
@Kloar, если запрос еще не получен сервером (например, большие многостраничные запросы), клиент может закрыть сокет, и это повлияет на сервер.
PHP проверяет прерванные запросы автоматически и также автоматически завершается. см. php.net/manual/en/function.ignore-user-abort.php
@ElephantHunter: не могли бы вы предоставить материалы для чтения по browser aborting request prematurely?
@hanshenrik Это правда только наполовину, прочтите документацию, прежде чем публиковать ее. Он работает только в CLI, который широко не используется, особенно для ajax.
@ViktorKoncsek нет, ignore_user_abort () также предназначен для веб-запросов (например, php + Apache)
Большинство методов jQuery Ajax возвращают объект XMLHttpRequest (или аналогичный), поэтому вы можете просто использовать abort().
См. Документацию:
var xhr = $.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
//kill the request
xhr.abort()
Обновлено: Начиная с jQuery 1.5 возвращаемый объект является оболочкой для собственного объекта XMLHttpRequest, называемого jqXHR. Этот объект, похоже, предоставляет все собственные свойства и методы, поэтому приведенный выше пример все еще работает. См. Объект jqXHR (документация jQuery API).
ОБНОВЛЕНИЕ 2:
Начиная с jQuery 3, метод ajax теперь возвращает обещание с дополнительными методами (например, прерывание), поэтому приведенный выше код все еще работает, хотя возвращаемый объект больше не является xhr. См. 3.0 блог здесь.
ОБНОВЛЕНИЕ 3: xhr.abort() все еще работает на jQuery 3.x. Не думайте, что обновление 2 правильный. Дополнительная информация о репозитории jQuery на Github.
Не могли бы вы подробнее рассказать, что именно делает abort ()?
Это похоже на нажатие кнопки «Стоп» в браузере. Он отменяет запрос. Затем вы можете повторно использовать тот же объект XHR для другого запроса.
@brad К сожалению, abort не закрывает установленное соединение с сервером, поэтому success все равно будет вызываться. Это очень проблематично для реализаций Comet с длинным опросом.
@ErvWalter Вы можете отправить другой запрос, который отменяет предыдущий.
@JoeCoderGuy: Я не уверен. Сервер по-прежнему будет делать это, но в моих тестах (по крайней мере, в Chrome v23) метод успеха javascript не вызывается.
@ user420667 У меня должна быть странная версия, потому что она не отменяет мою (та же версия). Я видел по другому вопросу, что выполнение этого на локальном хосте может не дать достаточно времени для отмены stackoverflow.com/questions/8584402/…
В моих тестах запрос прерывается в браузере, но метод .fail () вызывается с jqXHR, status = 0 и jqXHR, statusMessage = "abort"
для nodejs вызовите req.on('close', function() { }), чтобы определить, вызвала ли сторона javascript .abort()
В некоторых случаях я заметил, что нажатие и удерживание кнопки выхода отменяет запросы AJAX.
Он больше не будет работать для jQuery 3.0 blog.jquery.com/2016/01/14/jquery-3-0-beta-released
вы можете использовать return false, если выполняется определенное условие
Поскольку это такой высокий ответ, в нем действительно должно быть отражено, что это больше не работает (как упомянул @jcubic)
.abort() у меня все еще работает в jQuery 3.2.1. Этот комментарий в связанной проблеме github члена основной группы jQuery, похоже, подразумевает, что этот ответ неверен и что .abort() не был удален.
выдает ошибку для AjaxHelper: .abort () не является функцией
Сохраните сделанные вызовы в массиве, затем вызовите xhr.abort () для каждого.
ОГРОМНАЯ ПРЕДОСТЕРЕЖЕНИЕ: вы можете прервать запрос, но это только на стороне клиента. Серверная сторона все еще может обрабатывать запрос. Если вы используете что-то вроде PHP или ASP с данными сеанса, данные сеанса блокируются до завершения ajax. Итак, чтобы позволить пользователю продолжить просмотр веб-сайта, вы должны вызвать session_write_close (). Это сохраняет сеанс и разблокирует его, чтобы другие страницы, ожидающие продолжения, продолжили работу. Без этого несколько страниц могут ждать снятия блокировки.
поскольку вы всегда отменяете предыдущий, разве вы не можете просто всегда это делать? (и нет необходимости использовать массив)
Нам просто нужно было обойти эту проблему и протестировать три разных подхода.
var Ajax1 = {
call: function() {
if (typeof this.xhr !== 'undefined')
this.xhr.abort();
this.xhr = $.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
//process response
}
});
}
};
var Ajax2 = {
counter: 0,
call: function() {
var self = this,
seq = ++this.counter;
$.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
if (seq === self.counter) {
//process response
}
}
});
}
};
var Ajax3 = {
active: false,
call: function() {
if (this.active === false) {
this.active = true;
var self = this;
$.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
//process response
},
complete: function() {
self.active = false;
}
});
}
}
};
$(function() {
$('#button').click(function(e) {
Ajax3.call();
});
})<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id = "button" type = "button" value = "click" />В нашем случае мы решили использовать подход №3, так как он снижает нагрузку на сервер. Но я не на 100% уверен, что jQuery гарантирует вызов метода .complete () - это может привести к тупиковой ситуации. В наших тестах мы не смогли воспроизвести такую ситуацию.
У меня была проблема с опросом, и как только страница была закрыта, опрос продолжился, поэтому в моем случае пользователь пропустил обновление, поскольку значение mysql устанавливалось в течение следующих 50 секунд после закрытия страницы, хотя я убил запрос ajax, я разобрался, используя $ _SESSION для установки, что var не будет обновляться в опросе, пока он не закончится и не начнется новый, поэтому я установил значение в моей базе данных как 0 = offpage, в то время как я опрос. Я запрашиваю эту строку и возвращаю false; когда это 0, поскольку запрос в опросе, очевидно, даст вам текущие значения ...
Я надеюсь это помогло
Просто используйте ajax.abort (), например, вы можете прервать любой ожидающий запрос ajax перед отправкой другого, подобного этому
//check for existing ajax request
if (ajax){
ajax.abort();
}
//then you make another ajax request
$.ajax(
//your code here
);
Я использовал решение для поиска в реальном времени, и мне нужно было отменить ожидающие запросы, которые могли занять больше времени, чем последний / самый последний запрос.
В моем случае я использовал что-то вроде этого:
//On document ready
var ajax_inprocess = false;
$(document).ajaxStart(function() {
ajax_inprocess = true;
});
$(document).ajaxStop(function() {
ajax_inprocess = false;
});
//Snippet from live search function
if (ajax_inprocess == true)
{
request.abort();
}
//Call for new request
Запросы AJAX могут не выполняться в том порядке, в котором они были запущены. Вместо прерывания вы можете выбрать игнорировать для всех ответов AJAX, кроме самого последнего:
Примерный набросок кода:
var xhrCount = 0;
function sendXHR() {
// sequence number for the current invocation of function
var seqNumber = ++xhrCount;
$.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
// this works because of the way closures work
if (seqNumber === xhrCount) {
console.info("Process the response");
} else {
console.info("Ignore the response");
}
});
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last
// one will trigger "Process the response" message
Из-за оговорок об отмене запроса XHR (см. Другие комментарии на этой странице), это, вероятно, лучший и самый простой вариант.
Как отметили многие участники потока, сервер по-прежнему будет обрабатывать запрос только потому, что запрос прерывается на стороне клиента. Это создает ненужную нагрузку на сервер, потому что он выполняет работу, которую мы перестали слушать во внешнем интерфейсе.
Проблема, которую я пытался решить (с которой могут столкнуться и другие), заключается в том, что, когда пользователь вводил информацию в поле ввода, я хотел запустить запрос на ощущение типа Google Instant.
Чтобы избежать ненужных запросов и поддерживать оперативность интерфейса, я сделал следующее:
var xhrQueue = [];
var xhrCount = 0;
$('#search_q').keyup(function(){
xhrQueue.push(xhrCount);
setTimeout(function(){
xhrCount = ++xhrCount;
if (xhrCount === xhrQueue.length) {
// Fire Your XHR //
}
}, 150);
});
По сути, это будет отправлять один запрос каждые 150 мс (переменная, которую вы можете настроить для своих нужд). Если у вас возникли проблемы с пониманием того, что именно здесь происходит, запишите xhrCount и xhrQueue в консоль непосредственно перед блоком if.
Всегда лучше делать что-то подобное.
var $request;
if ($request != null){
$request.abort();
$request = null;
}
$request = $.ajax({
type : "POST", //TODO: Must be changed to POST
url : "yourfile.php",
data : "data"
}).done(function(msg) {
alert(msg);
});
Но гораздо лучше, если вы проверите оператор if, чтобы проверить, является ли запрос ajax нулевым или нет.
Я также проверяю, выполняется ли запрос, но я использую логическое значение, так как оно легче.
Просто вызовите xhr.прерывание (), будь то объект jquery ajax или собственный объект XMLHTTPRequest.
пример:
//jQuery ajax
$(document).ready(function(){
var xhr = $.get('/server');
setTimeout(function(){xhr.abort();}, 2000);
});
//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);
надежного способа сделать это нет, и я бы даже не пробовал, раз запрос уже на ходу; способ разумной реакции Только - это игнорировать ответ.
в большинстве случаев это может произойти в таких ситуациях, как: пользователь слишком часто нажимает кнопку, запускающую несколько последовательных XHR, здесь у вас есть много вариантов, либо заблокировать кнопку до тех пор, пока не будет возвращен XHR, либо даже не запускать новый XHR, пока другой запускает подсказку пользователь может откинуться назад - или отказаться от любого ожидающего ответа XHR, кроме недавнего.
Следующий код показывает как инициирование, так и прерывание запроса Ajax:
function libAjax(){
var req;
function start(){
req = $.ajax({
url: '1.php',
success: function(data){
console.info(data)
}
});
}
function stop(){
req.abort();
}
return {start:start,stop:stop}
}
var obj = libAjax();
$(".go").click(function(){
obj.start();
})
$(".stop").click(function(){
obj.stop();
})
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type = "button" class = "go" value = "GO!" >
<input type = "button" class = "stop" value = "STOP!" >
Пожалуйста, объясните, как это решает вопрос. Это поможет OP и другим будущим поисковикам.
Я поделился демонстрация, который демонстрирует, как отменить запрос AJAX - если данные не возвращаются с сервера в течение заранее определенного времени ожидания.
HTML:
<div id = "info"></div>
КОД JS:
var isDataReceived= false, waitTime= 1000;
$(function() {
// Ajax request sent.
var xhr= $.ajax({
url: 'http://api.joind.in/v2.1/talks/10889',
data: {
format: 'json'
},
dataType: 'jsonp',
success: function(data) {
isDataReceived= true;
$('#info').text(data.talks[0].talk_title);
},
type: 'GET'
});
// Cancel ajax request if data is not loaded within 1sec.
setTimeout(function(){
if (!isDataReceived)
xhr.abort();
},waitTime);
});
Если xhr.abort(); вызывает перезагрузку страницы,
Затем вы можете установить onreadystatechange перед прерыванием, чтобы предотвратить:
// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();
Вы можете прервать любой непрерывный вызов ajax с помощью этого
<input id = "searchbox" name = "searchbox" type = "text" />
<script src = "http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type = "text/javascript">
var request = null;
$('#searchbox').keyup(function () {
var id = $(this).val();
request = $.ajax({
type: "POST", //TODO: Must be changed to POST
url: "index.php",
data: {'id':id},
success: function () {
},
beforeSend: function () {
if (request !== null) {
request.abort();
}
}
});
});
</script>
Это моя реализация, основанная на многих ответах выше:
var activeRequest = false; //global var
var filters = {...};
apply_filters(filters);
//function triggering the ajax request
function apply_filters(filters){
//prepare data and other functionalities
var data = {};
//limit the ajax calls
if (activeRequest === false){
activeRequest = true;
}else{
//abort if another ajax call is pending
$request.abort();
//just to be sure the ajax didn't complete before and activeRequest it's already false
activeRequest = true;
}
$request = $.ajax({
url : window.location.origin + '/your-url.php',
data: data,
type:'POST',
beforeSend: function(){
$('#ajax-loader-custom').show();
$('#blur-on-loading').addClass('blur');
},
success:function(data_filters){
data_filters = $.parseJSON(data_filters);
if ( data_filters.posts ) {
$(document).find('#multiple-products ul.products li:last-child').after(data_filters.posts).fadeIn();
}
else{
return;
}
$('#ajax-loader-custom').fadeOut();
},
complete: function() {
activeRequest = false;
}
});
}
Может, я неправильно понял вопрос, но нельзя ли просто использовать
$.ajaxStop?