несколько вызовов jquery-ajax

Я использую следующий код для нескольких запросов ajax, подобных этому:

запросить 1 запуск | запросить 1 завершение | запрос 2 start | запросить 2 завершить | ...

Это код:

var startingpoint = fireRequest(1);
    $.each(types,function(ix,type) 
    {
       startingpoint = startingpoint.pipe( function() 
       {
          alert(startingpoint.status); // undefined
          return fireRequest(type);
        });
    });

fireRequest — это просто переход к правильной функции ajax, которая возвращает $.ajax(...)

Я бы хотел, чтобы цепочка останавливалась при сбое одного запроса. Я начал его реализовывать, и в качестве теста я хотел бы предупредить о статусе объекта ajax, но он показывает «неопределенное». Как я могу получить статус?


person PoeHaH    schedule 03.10.2012    source источник
comment
Это может звучать глупо, но почему бы вам просто не установить для своих вызовов AJAX значение async: false (отменив букву A в AJAX)? Или я неправильно понял ваш вопрос?   -  person m90    schedule 07.10.2012
comment
если я поставлю «Async: false», это действительно будет такое же поведение, как здесь, но тогда как мне остановить запросы, когда 1 терпит неудачу? Я чувствую, что код в моем вопросе более правильный   -  person PoeHaH    schedule 07.10.2012
comment
Вы можете просто иметь массив, содержащий запросы, которые вы просто обрабатываете один за другим. В случае успеха вы переходите к следующему пункту, если вызов не работает, вы прерываетесь. Тем не менее, я согласен, что Non-Async AJAX довольно бессмысленен. Вы уже видели $.when?   -  person m90    schedule 07.10.2012
comment
да. это удобная функция, но и в .when() я не могу увидеть статус из результата предыдущего вызова. Может я что-то не так делаю, отсюда и вопрос :)   -  person PoeHaH    schedule 07.10.2012
comment
Вы читали глобальные обработчики событий Ajax?   -  person Ron van der Heijden    schedule 09.10.2012


Ответы (3)


Поведение, которое вы пытаетесь реализовать, уже является поведением метода .pipe(). Он принимает два обратных вызова в качестве параметров и будет выполнять ТОЛЬКО сделанный обратный вызов и продолжит работу по цепочке, если предыдущий запрос будет успешным. Это можно проиллюстрировать в следующем jsfiddle: http://jsfiddle.net/dflor003/Vq2YF/ ( Примечание: откройте это в браузере со встроенной поддержкой JSON.stringify и поддержкой console.log)

Если вы хотите проверить статус запроса, он примет статус в качестве второго параметра для обратного вызова done. Более подробную информацию можно найти на сайте документации API jQuery: http://api.jquery.com/deferred.pipe/

person DanilF    schedule 09.10.2012
comment
БАМ! ответил на вопрос, как я этого хотел, и рабочий пример. Большое спасибо! - person PoeHaH; 09.10.2012

JS-пример 1

этот код предполагает, что вы хотите прервать другие запросы, если какой-либо один запрос не будет выполнен (через ответ 404 или 500 или время ожидания), и вам не нужно оценивать ответ данных, чтобы определить сценарий отказа бизнес-логики. $.when()

Метод разрешит свой главный Deferred, как только разрешатся все Deferred, или отклонит главный Deferred, как только будет отклонен один из Deferred.

    $.when(fireRequest(1), fireRequest(2),fireRequest(3))
  .then(myAllSuccessfulFunc, oneFailedFunc);

function myAllSuccesfulFunc(req1,req2,req3){
//everything returned a 200.
   alert("these are not the droids you are looking for");
};
function oneFailedFunc(req1,req2,req3){
    //* each req looks like [ "not success", statusText, jqXHR ] */
//feel free to check what failed, but I don't know what you need

   req1[2].abort();
   req2[2].abort();
   req3[2].abort();
};

js пример 2

вам действительно нужно проанализировать успешный запрос данных в ответе, чтобы увидеть, должны ли вы отказать другим запросам из-за логики из серверной части.

var stop = 4;
//if you are sure fireRequest(x) returns a good promise object, do this:
callNext(fireRequest(1),1);

function callNext(promise, currentIndex){
   promise.done(function(ajaxArgs){
   var jqXHR = ajaxArgs[2];
//replace this with some logic check that makes sense to your app
   if(/error/.test(jqXHR.responseText)){
    //do something
   }else if(currentIndex <stop){
    callNext(fireRequest(currentIndex+1),currentIndex+1);
   }).fail(function(ajaxArgs){
   //server returned a 404, or a 500, or something not a success.
   });
};
person DefyGravity    schedule 08.10.2012

Я думаю, проблема в том, что $.Deferred и ему подобные предназначены для обработки асинхронных и параллельных процедур, поэтому вам всегда придется их как-то обманывать, если вы хотите, чтобы они действовали так, как вы это описываете.

Если вы хотите/нужно обрабатывать ваши вызовы один за другим (используя AJAX), я бы предложил поместить их в массив и использовать простую рекурсивную функцию для циклического прохождения этого массива до тех пор, пока все вызовы не будут выполнены. или один из них вышел из строя.

В основном это будет работать так:

var requests = [
  {
  url : '/serviceA'
  data : myParams4ServiceA
  },
  ...
  {
  url : '/serviceZ'
  data : myParams4ServiceZ
  }
];

Теперь, когда у вас есть массив запросов AJAX, вы можете создать рекурсивную функцию, которая будет обрабатывать их один за другим:

function work(){

$.ajax(requests[0]).done(function(data){
  //handle data here
  requests.shift(); //request is done and can be removed from the Array, request[0] will now be the next request in the queue

  if (requests.length){
    work(); //function calls itself again if there's still need for it
  } else {
    // we are done!
  }

}).fail(function(e){
  //call failed -> handle error
});

}

work();

См. эту скрипту для примера успешной цепочки и этот для цепочки, в которой произошел сбой.

Другой возможностью может быть установка вызовов AJAX на async : false (обратите внимание, что это устарело в jQuery 1.8+: «Начиная с jQuery 1.8, использование async: false с jqXHR ($.Deferred) устарело; вы должны использовать обратные вызовы complete/success/error.", который снова указывает нам на резервное копирование), и используйте простую цепочку $.when().then().fail(), которую вы применяете к своему массиву запросов, например:

$.when.apply($, requests).then(function(){

    $.each(arguments, function(){
        //do stuff with your data
    });

}).fail(function(){

    //handle the error

});

Поскольку ваши вызовы теперь блокируются, это также будет обрабатывать их подряд. См. также скрипку.

person m90    schedule 08.10.2012