Как мне отправить неудачный запрос ajax?
У меня есть несколько ajax запросов некоторые данные запроса каждую минуту другие инициируются пользователем через ui.
$.get('/myurl', data).done(function( data ){
// do stuff..
});
Запрос может завершиться неудачно из-за сбоя проверки подлинности.
Я установил глобальный метод .ajaxError()
для обнаружения любых неудачных запросов.
$(document).ajaxError(function( e, jqxhr ){
// Correct error..
});
После того, как я поймаю ошибку я reset.
Сброс работы авторизации, но пользователю необходимо вручную инициировать вызов ajax (через ui).
Как отправить повторно запрос с использованием отправленного jqxhr?
(Я использую jQuery для ajax)
Ответы
Ответ 1
Нашел этот пост, который предлагает хорошее решение этой проблемы.
Главное - использовать $.ajaxPrefilter и заменить ваш обработчик ошибок на собственный, который проверяет наличие повторов и выполняет повторные попытки, используя замыкание "originalOptions".
Я публикую код на тот случай, если в будущем он будет отключен. Опять же, кредит принадлежит первоначальному автору.
// register AJAX prefilter : options, original options
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
originalOptions._error = originalOptions.error;
// overwrite error handler for current request
options.error = function( _jqXHR, _textStatus, _errorThrown ){
if (... it should not retry ...){
if( originalOptions._error ) originalOptions._error( _jqXHR, _textStatus, _errorThrown );
return;
};
// else... Call AJAX again with original options
$.ajax( originalOptions);
};
});
Ответ 2
В этом случае я бы написал конкретный обработчик для кода состояния 403
, что означает несанкционированный (мой сервер также вернет 403). Из jquery ajax docs вы можете сделать
$.ajax({
statusCode: {
403: function() {
relogin(onSuccess);
}
}
});
чтобы достичь этого.
В этом обработчике я бы назвал метод relogin
, передав функцию, которая фиксирует, что делать, когда логин завершается успешно. В этом случае вы можете передать метод, содержащий вызов, который вы хотите запустить снова.
В приведенном выше коде relogin
должен вызывать код входа, а onSuccess
должен быть функцией, которая обертывает код, который вы выполняете каждую минуту.
EDIT - на основе вашего пояснения в комментарии, что этот сценарий случается для нескольких запросов, я лично создам API для вашего приложения, которое захватывает взаимодействие с сервером.
app = {};
app.api = {};
// now define all your requests AND request callbacks, that way you can reuse them
app.api.makeRequest1 = function(..){..} // make request 1
app.api._request1Success = function(...){...}// success handler for request 1
app.api._request1Fail = function(...){...}// general fail handler for request 1
/**
A method that will construct a function that is intended to be executed
on auth failure.
@param attempted The method you were trying to execute
@param args The args you want to pass to the method on retry
@return function A function that will retry the attempted method
**/
app.api.generalAuthFail = function(attempted, args){
return function(paramsForFail){ // whatever jquery returns on fail should be the args
if (attempted) attempted(args);
}
}
поэтому с помощью этой структуры в вашем методе request1
вы бы сделали что-то вроде
$().ajax({
....
statusCode: {
403: app.api.generalAuthFail(app.api.request1, someArgs);
}
}}
generalAuthFailure
вернет обратный вызов, который выполняет метод, в котором вы проходите.
Ответ 3
Код ниже сохранит исходный запрос, и он попытается добиться успеха 3 раза.
var tries = 0;
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
if(tries < 3){
tries++;
$.ajax(this).done(function(){tries=0;});
}
});
Ответ 4
Возможно, вам удастся присвоить имена каждой из ваших функций, а затем напомнить их, как указано в ответах hvgotcodes.
или
Вы можете использовать функцию повторного использования для установки запроса при расширении значений по умолчанию:
function getRequest( options ){
var // always get json
defaults = { dataType: 'json' },
settings = $.extend( defaults, options );
return // send initial ajax, if it all good return the jqxhr object
$.ajax( settings )
// on error
.fail(function( jqxhr, e ){
// if the users autherization has failed out server responds with a 401
if( jqxhr.status === 401 ){
// Authenticate user again
resetAuthentication()
.done(function(){
// resend original ajax also triggering initial callback
$.ajax( settings );
});
}
});
};
Чтобы использовать вышеуказанную функцию, вы должны написать что-то вроде этого:
getRequest({
url: 'http://www.example.com/auth.php',
data: {user: 'Mike', pass: '12345'},
success: function(){ // do stuff }
});
getRequest()
можно было бы сделать рекурсивным и/или преобразовать в плагин jQuery, но этого было достаточно для моих нужд.
Примечание. Если функция resetAutentication может быть скрытой, getRequest()
должна быть рекурсивной.