Отмена Ajax-запросов с помощью jQuery
Вопрос:
Возможно ли с помощью jQuery отменить или прервать Ajax-запрос, на который я еще не получил ответ?
5 ответ(ов)
Чтобы сохранить вызовы, которые вы делаете, в массиве, а затем вызвать xhr.abort()
для каждого из них, вы можете воспользоваться следующим подходом:
let requests = [];
// Пример функции, выполняющей AJAX-запрос
function makeRequest(url) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
// Сохраняем запрос для последующего прерывания
requests.push(xhr);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// Обработка ответа
if (xhr.status === 200) {
console.log(xhr.responseText);
}
}
};
xhr.send();
}
// Прерывание всех запросов
function abortAllRequests() {
requests.forEach(xhr => xhr.abort());
requests = []; // Очищаем массив после прерывания
}
ОГРОМНОЕ ПРЕДУПРЕЖДЕНИЕ: Вы можете прервать запрос на стороне клиента, но на сервере запрос все еще может обрабатываться. Если вы используете такие технологии, как PHP или ASP с данными сессий, сессия будет заблокирована до завершения AJAX-запроса. Чтобы позволить пользователю продолжать навигацию по сайту, необходимо вызвать session_write_close()
. Это позволит сохранить сессию и разблокировать её, чтобы другие страницы могли продолжить загрузку. Без этого несколько страниц могут ожидать снятия блокировки.
Это асинхронный
запрос, что означает, что после его отправки он уже «вне» вашего контроля.
Если ваш сервер начинает выполнение очень ресурсоемкой операции в ответ на AJAX
запрос, лучший вариант — настроить сервер на прием запросов на отмену, и отправить отдельный AJAX
запрос, уведомляющий сервер о необходимости остановить выполнение текущей операции.
В противном случае, просто игнорируйте ответ AJAX
.
Наилучшей практикой является использование следующего кода:
var $request;
if ($request != null) {
$request.abort();
$request = null;
}
$request = $.ajax({
type: "POST", // TODO: Нужно изменить на POST
url: "yourfile.php",
data: "data"
}).done(function(msg) {
alert(msg);
});
Однако гораздо лучше добавить проверку в условии, чтобы убедиться, что AJAX-запрос не равен null
.
Мы столкнулись с этой проблемой и протестировали три разных подхода.
- Обрабатываем отмену запроса, как предложил @meouw.
- Выполняем все запросы, но обрабатываем только результат последнего.
- Предотвращаем новые запросы, пока предыдущий ещё выполняется.
var Ajax1 = {
call: function() {
if (typeof this.xhr !== 'undefined')
this.xhr.abort();
this.xhr = $.ajax({
url: 'ваш/долгий/запрос/путь',
type: 'GET',
success: function(data) {
// обработка ответа
}
});
}
};
var Ajax2 = {
counter: 0,
call: function() {
var self = this,
seq = ++this.counter;
$.ajax({
url: 'ваш/долгий/запрос/путь',
type: 'GET',
success: function(data) {
if (seq === self.counter) {
// обработка ответа
}
}
});
}
};
var Ajax3 = {
active: false,
call: function() {
if (this.active === false) {
this.active = true;
var self = this;
$.ajax({
url: 'ваш/долгий/запрос/путь',
type: 'GET',
success: function(data) {
// обработка ответа
},
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="нажми" />
В нашем случае мы решили использовать третий подход, так как он создает меньшую нагрузку на сервер. Однако я не совсем уверен, гарантирует ли jQuery вызов метода .complete()
, так как это может привести к ситуации взаимной блокировки. В наших тестах нам не удалось воспроизвести такую ситуацию.
Вы можете просто вызвать xhr.abort()
, независимо от того, используете ли вы объект Ajax из jQuery или nativный объект XMLHttpRequest
.
Вот пример кода:
// Ajax с использованием jQuery
$(document).ready(function(){
var xhr = $.get('/server');
setTimeout(function(){ xhr.abort(); }, 2000);
});
// Нативный XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
xhr.send();
setTimeout(function(){ xhr.abort(); }, 2000);
В данном примере мы выполняем запрос на сервер, а затем через 2 секунды прерываем его с помощью метода abort()
.
Как загружать файлы асинхронно с помощью jQuery?
Как заставить jQuery выполнять синхронный запрос Ajax вместо асинхронного?
jQuery AJAX: Отправка формы
Кэширует ли Safari на iOS 6 результаты $.ajax?
Запрос Ajax возвращает 200 OK, но вместо успеха срабатывает событие ошибки