Trabalhando corretamente com solicitações Ajax no WordPress
Sempre que você está trabalhando com APIs de terceiros e está fazendo isso de forma assíncrona, sempre há a chance de que o que você está solicitando retorne um resultado indesejado.
Talvez seja um código de erro, talvez seja um aviso, ou talvez seja uma simples mensagem dizendo algo como "Ainda estamos processando sua solicitação do nosso lado".
Em cada caso, você geralmente pode lidar com eles no lado do servidor muito bem e deixar o lado do cliente saber como lidar com isso. Mas se você estiver lidando com o último caso, é aí que você é bloqueado pelo processamento de terceiros; há outras coisas que você pode fazer para lidar melhor com essa situação.
Por exemplo, neste último caso, é melhor esperar um pouco e fazer a requisição novamente para ver se a API tem uma resposta diferente para você.
Mas ao fazer isso, requer Ajax, que obviamente requer JavaScript. Um dos métodos óbvios, ainda mais datados, de fazer isso é usar setInterval.
O problema com isso, porém, é que ele cria uma pilha de solicitações e, assim que a resposta estiver pronta, cada item da pilha receberá a mesma resposta.
Isso pode afetar drasticamente qualquer servidor. E há maneiras melhores de fazer isso.
Trabalhando corretamente com solicitações Ajax
Como de costume, já que o WordPress vem com jQuery, vou usar isso; no entanto, também exorto você – se ainda não o fez – a olhar para o Ajax no ES6 para ter uma ideia de como fazer isso nativamente.
De qualquer forma, a ideia é esta: em vez de configurar algum intervalo, use as funções internas do Ajax para avaliar a resposta corretamente. E somente sob certas condições, acione a função novamente.
Caso em questão: o método $.post do jQuery oferece algumas funções que podem ser usadas exatamente para isso. Por exemplo, oferece métodos como:
- feito()
- falhou()
- sempre()
E cada um deles deve ser executado sob certas condições das quais mostrarei em alguns exemplos de código momentaneamente.
Antes de fazer isso, porém, é importante entender que existem vários parâmetros que estou enviando com os quais suponho que você esteja familiarizado:
- o URL do WordPress Ajax (que definirei como acme.ajax_url),
- uma URL para a postagem que estamos visualizando (que será armazenada em uma variável sUrl),
- e um nonce de segurança que chamarei de acme.security
Se algum dos itens acima não estiver claro, leia as páginas vinculadas para ver como isso é alcançado.
Mas com isso dito, aqui está a ideia por trás de como você pode gerenciar respostas repetidas do Ajax sem setInterval.
1 Uma Função para o Trabalho
A primeira coisa que você precisa fazer é envolver o trabalho que você vai fazer em sua própria função. Isso significa que você pode chamá-lo de qualquer outro lugar no aplicativo do lado do cliente ou até mesmo no contexto de um cronômetro (se absolutamente necessário).
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() {
// ..
});
}
E, como você pode ver, eu fui em frente e apaguei algumas das funções que mencionei acima.
2 Lide com o sucesso
No caso de sucesso, você pode usar uma função anônima como retorno de chamada para a função $.post. O argumento principal com o qual você deve se preocupar é o argumento de resposta .
Normalmente, gosto que minhas respostas tenham um atributo de sucesso e um atributo de falha. Isso torna mais fácil lidar com um caso sempre que a resposta for totalmente bem-sucedida, mas os dados que retornaram do servidor não foram o que eu esperava.
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() {
// ...
});
}
Isso não significa necessariamente que houve uma falha. Significa apenas que o que eu estava procurando recuperar não foi encontrado.
3 Lidar com a falha
Por outro lado, há momentos em que algo pode falhar. Por que isso acontece pode ser por vários motivos e para entendê-lo corretamente, vale a pena inspecionar os argumentos que o retorno de chamada fornece, ou seja, o status e o erro.
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() {
// ...
});
}
Não posso dar exemplos concretos aqui porque cada API é diferente; no entanto, recomendo pelo menos gravar dados no console para que você possa entender o que está acontecendo e como lidar com isso em um nível de código.
4 Lidar com o Caso Incondicional
Nesse caso específico, essa função será acionada independentemente de algo ter sido bem-sucedido ou não.
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.
});
}
Esta função não é algo que você pode sempre precisar (sem trocadilhos), mas é uma opção sólida para, digamos, ocultar uma barra de progresso ou exibir algo na interface do usuário. Isso pode dar ao usuário um feedback de que a solicitação concluiu seu trabalho (novamente, independentemente de falha ou sucesso).
5 Lide com o sucesso, novamente
Finalmente, o método done é muito parecido com o método de sucesso, mas pense nele como destinado a ser chamado uma segunda vez.
Isso significa que depois que a resposta voltar do servidor com o argumento de resposta, a mesma coisa será acionada novamente quando todo o resto for concluído.
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.
});
}
Isso lhe dá outra chance de fazer o que quiser com o argumento de resposta mais uma vez antes que tudo seja concluído.
Eu raramente uso isso, mas houve momentos em que eu quis remover um elemento somente depois que algo foi feito, todos os outros processamentos foram feitos e a resposta foi bem-sucedida.
Talvez você não precise de tudo
Obviamente, grande parte do código acima é apenas para uma demonstração de como lidar com solicitações. Mas o objetivo é mostrar como lidar com a requisição sem a necessidade de definir intervalos para empilhar as requisições. Em vez disso, você aproveita as funções pré-existentes para, digamos, chamar a função novamente se houver um erro.
De qualquer forma, isso pode ser um exagero para alguns, mas para outros que estão acostumados a usar setInterval, pode ser uma maneira muito melhor de gerenciar solicitações Ajax que não se acumulam e disparar a mesma solicitação para o servidor quando uma resposta já foi gerenciou.
E, em última análise, esse é o objetivo: código eficiente que recupera as informações de que precisamos sem sobrecarregar a API de terceiros ou o navegador do nosso próprio usuário.
