Правильная работа с запросами Ajax в WordPress
Всякий раз, когда вы работаете со сторонними API и делаете это асинхронно, всегда есть шанс, что все, что вы запрашиваете, вернет нежелательный результат.
Возможно, это код ошибки, возможно, это предупреждение или, может быть, это простое сообщение, в котором говорится что-то вроде «Мы все еще обрабатываем ваш запрос с нашей стороны».
В каждом случае вы обычно можете нормально обрабатывать их на стороне сервера и сообщать стороне клиента, как с этим справиться. Но если вы имеете дело с последним случаем, именно здесь вы заблокированы сторонней обработкой; есть и другие вещи, которые вы можете сделать, чтобы лучше справиться с этой ситуацией.
Например, в последнем случае лучше немного подождать, а затем снова сделать запрос, чтобы увидеть, есть ли у API другой ответ для вас.
Но при этом требуется Ajax, который, очевидно, требует JavaScript. Один из очевидных, но более устаревших способов сделать это — использовать setInterval.
Однако проблема заключается в том, что он создает стек запросов, а затем, когда ответ готов, каждый элемент в стеке получит один и тот же ответ.
Это может сильно повлиять на любой данный сервер. И есть лучшие способы сделать это.
Правильная работа с Ajax-запросами
Как обычно, поскольку WordPress поставляется с jQuery, я буду использовать его; тем не менее, я также призываю вас — если вы еще этого не сделали — взглянуть на Ajax в ES6, чтобы получить представление о том, как это сделать изначально.
В любом случае, идея такова: вместо того, чтобы устанавливать какой-то интервал, используйте встроенные функции Ajax для правильной оценки ответа. И только при определенных условиях запускать функцию снова.
Показательный пример: метод jQuery $.post предлагает некоторые функции, которые можно использовать именно для этого. Например, он предлагает такие методы, как:
- Выполнено()
- потерпеть неудачу()
- всегда()
И каждый из них предназначен для запуска при определенных условиях, которые я сейчас покажу в некоторых примерах кода.
Однако прежде чем сделать это, важно понять, что есть несколько параметров, которые я отправляю, и я полагаю, что вы знакомы с ними:
- URL-адрес WordPress Ajax (который я обозначу как acme.ajax_url),
- URL поста, который мы просматриваем (который будет храниться в переменной sUrl),
- и одноразовый номер безопасности, который я буду называть acme.security
Если что-то из вышеперечисленного неясно, прочитайте связанные страницы, чтобы увидеть, как это достигается.
Но с учетом сказанного, вот идея того, как вы можете управлять повторяющимися ответами Ajax без setInterval.
1 Функция для работы
Первое, что вам нужно сделать, это обернуть работу, которую вы собираетесь выполнять, в ее собственную функцию. Это означает, что вы можете вызывать его из любого места в клиентском приложении или даже в контексте таймера (если это абсолютно необходимо).
Например :
var _processArticle = function() {
var request =
$.post(acme.ajax_url, {
action: 'acme_get_data',
url: sUrl
security: acme.security
}, function(response) {
// ...
})
.done(function(response) {
// ...
})
.fail(function(xhr, status, error) {
// ...
})
.always(function() {
// ..
});
}
И, как видите, я пошел дальше и заглушил некоторые функции, о которых упоминал выше.
2 Справиться с успехом
В случае успеха вы можете использовать анонимную функцию в качестве обратного вызова для функции $.post. Основной аргумент, который вас должен волновать, — это аргумент ответа .
Как правило, мне нравится, чтобы мой ответ имел атрибут успеха и атрибут неудачи. Это упрощает обработку случая, когда ответ полностью успешен, но данные, возвращенные с сервера, не соответствуют моим ожиданиям.
var _processArticle = function() {
var request =
$.post(acme.ajax_url, {
action: 'acme_get_data',
url: sUrl
security: acme.security
}, function(response) {
// Abort all request operations.
if (false === response.success) {
request.abort();
}
// Handle the successful response by modifying the DOM.
})
.done(function(response) {
// ...
})
.fail(function(xhr, status, error) {
// ...
})
.always(function() {
// ...
});
}
Это не обязательно означает, что произошел сбой. Это просто означает, что то, что я искал, не было найдено.
3 Справиться с ошибкой
С другой стороны, бывают случаи, когда что-то может выйти из строя. Это происходит по разным причинам, и чтобы понять это правильно, стоит изучить аргументы, предоставляемые обратным вызовом, а именно статус и ошибку.
var _processArticle = function() {
var request =
$.post(acme.ajax_url, {
action: 'acme_get_data',
url: sUrl
security: acme.security
}, function(response) {
// Abort all request operations.
if (false === response.success) {
request.abort();
}
// Handle the successful response by modifying the DOM like flashing the first image.
$('img:first').fadeTo('fast', 0.5, function() {
$(this).fadeTo('fast', 1);
});
})
.done(function(response) {
// ...
})
.fail(function(xhr, status, error) {
console.log('There was a problem with contacting the API.');
console.log('The status was:');
console.log(status);
console.log('The error was:')
cosole.log(error);
})
.always(function() {
// ...
});
}
Я не могу привести здесь конкретные примеры, потому что каждый API отличается; тем не менее, я рекомендую по крайней мере записывать данные в консоль, чтобы вы могли понять, что происходит и как вы можете изящно обрабатывать это на уровне кода.
4 Обработка безусловного случая
В этом конкретном случае эта функция сработает независимо от того, было ли что-то успешным или нет.
var _processArticle = function() {
var request =
$.post(acme.ajax_url, {
action: 'acme_get_data',
url: sUrl
security: acme.security
}, function(response) {
// Abort all request operations.
if (false === response.success) {
request.abort();
}
// Handle the successful response by modifying the DOM like flashing the first image.
$('img:first').fadeTo('fast', 0.5, function() {
$(this).fadeTo('fast', 1);
});
})
.done(function(response) {
// ...
})
.fail(function(xhr, status, error) {
console.log('There was a problem with contacting the API.');
console.log('The status was:');
console.log(status);
console.log('The error was:')
console.log(error);
})
.always(function() {
// Regardless of what happens, this is where you can provide the user feedback.
});
}
Эта функция не всегда может понадобиться (без каламбура), но это надежный вариант, например, для скрытия индикатора выполнения или отображения чего-либо в пользовательском интерфейсе. Это может дать пользователю небольшую обратную связь о том, что запрос завершил свою работу (опять же, независимо от неудачи или успеха).
5 Снова справиться с успехом
Наконец, метод done очень похож на метод Success, но считайте, что он предназначен для повторного вызова.
Это означает, что после того, как ответ будет возвращен с сервера с аргументом ответа, то же самое сработает снова, как только все остальное завершится.
var _processArticle = function() {
var request =
$.post(acme.ajax_url, {
action: 'acme_get_data',
url: sUrl
security: acme.security
}, function(response) {
// Abort all request operations.
if (false === response.success) {
request.abort();
}
// Handle the successful response by modifying the DOM.
})
.done(function(response) {
// Display any additional changes you may want to make based on the respnse.
})
.fail(function(xhr, status, error) {
console.log('There was a problem with contacting the API.');
console.log('The status was:');
console.log(status);
console.log('The error was:')
console.log(error);
})
.always(function() {
// Regardless of what happens, this is where you can provide the user feedback.
});
}
Это дает вам еще один шанс сделать все, что вы хотите сделать с аргументом ответа, еще раз, прежде чем все будет завершено.
Я редко использую это, но были случаи, когда я хотел удалить элемент только после того, как что-то было сделано, вся остальная обработка была выполнена и ответ был успешным.
Может быть, вам не нужно все это
Очевидно, что большая часть приведенного выше кода предназначена только для демонстрации того, как обрабатывать запросы. Но цель состоит в том, чтобы показать, как обрабатывать указанный запрос без необходимости устанавливать интервалы для стека запросов. Вместо этого вы используете уже существующие функции, чтобы, скажем, снова вызвать функцию в случае ошибки.
В любом случае, для некоторых это может быть излишним, но для других, которые привыкли использовать setInterval, это может быть гораздо лучший способ управлять Ajax-запросами, которые не складываются, и отправлять один и тот же запрос на сервер, когда ответ уже был получен. удалось.
И, в конечном счете, это цель: эффективный код, который извлекает нужную нам информацию, не тормозя сторонний API или браузер нашего собственного пользователя.
