Как мне отправить неудачный запрос 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() должна быть рекурсивной.