2015-08-04 2 views
0

У меня проблема, когда у меня есть три вызова Ajax, которые мне нужно сделать, чтобы получить некоторые строки. Если какой-либо из них не работает, вместо этого мне нужно использовать строку по умолчанию. Я хочу, чтобы моя страница подождала, пока все строки не будут разрешены (или отклонены), прежде чем двигаться дальше.Как я могу быть уверенным, что группа отложенных дней решена или отклонена, прежде чем продолжить?

То, что я до сих пор выглядит примерно так:

var myObj = { 
    initialize: function(){ 
     // Start fetching this stuff right away 
     var that = this; 
     this.promise1 = $.ajax(url: 'url1').then(function(result){ 
      that.string1 = result 
     ).fail(function(){ 
      that.string1 = 'string1Default'; 
     }); 
     this.promise2 = $.ajax(url: 'url2').then(function(result){ 
      that.string2 = result 
     ).fail(function(){ 
      that.string2 = 'string2Default'; 
     }); 
     this.promise3 = $.ajax(url: 'url3').then(function(result){ 
      that.string3 = result 
     ).fail(function(){ 
      that.string3 = 'string3Default'; 
     }); 
    } 

    getStrings: function(){ 
     return { 
      string1: this.string1, 
      string2: this.string2, 
      string3: this.string3 
     }; 
    } 

    doThingWithStrings: function(callback){ 
     var that = this; 
     return $.when(this.promise1, this.promise2, this.promise3) 
      .always(function(){callback(that.getStrings())}) 
    } 
} 

myObj.initialize(); // start fetching 
// ... do some other stuff 
myObj.doThingWithStrings(loadThePageWithStrings); 

Есть две проблемы с этим. Один из них заключается в том, что он просто чувствует себя тяжелее, чем должно быть.

Вторая важная проблема заключается в том, что $ .when выполняет .done(), когда все были разрешены, но .fail(), как только все были отклонены. То, что мне действительно нужно, - это то, что выполняется после того, как все обещания уже не ожидаются, успешно ли они были решены или были отклонены. $. Кажется, почти, но не совсем, что я хочу. Я не хочу показывать страницу, пока я не извлечу (или не смог получить) каждую из трех строк. Как я могу это сделать?

+0

После дополнительных исследований (я обещаю, я посмотрел, прежде чем я это написал!) Я думаю, что, может быть, это дубликат [this] (http://stackoverflow.com/questions/6538470/jquery-deferred-waiting-for-multiple-ajax-requests-to-finish/13627555#13627555) – Sterno

ответ

0

answer you found не является полным ответом на этот вопрос. Это дает вам только часть пути.

Самое важное, что отсутствует, это правильная инъекция значений по умолчанию, которая является центральной для этого вопроса. Вы должны знать, как:

  • отлавливать ошибки Ajax,
  • впрыскивать по умолчанию,
  • неудачи превратить в успех.

Эти три вещи могут быть достигнуты очень просто путем формирования трех $.ajax(...).then(...) цепей, каждая из которых с обработчик ошибок, который возвращает обещание JQuery разрешенное с искомой строки по умолчанию:

$.ajax(...).then(null, function() { 
    return $.when('default'); 
}); 

Также .getStrings() должен возвращать Пообещать (обещание заполнить кешем). Если речь идет о асинхронно полученных данных, единственным надежным подходом является возврат обещания (абстракция данных), а не самих данных.

Чтобы сделать код аккуратнее, вы можете сделать несколько других вещей:

  • условно называют .initialize() от .getStrings() в случае, если она еще не была вызвана.
  • суммировать обещания в .initialize() и кэшировать полученные обещания, в отличие от кэширования трех обещаний jqXHR по отдельности.
  • очистка .doThingWithStrings() в пользу вызова .getStrings() напрямую. Нет никакого преимущества в использовании промежуточного метода, который принимает обратный вызов, когда объект, возвращенный .getStrings(), является обещанием, метод .then() сам будет принимать обратные вызовы с ошибками/ошибками.

Вот myObj:

var myObj = { 
    initialize: function() { 
     var promise1 = $.ajax({url: 'url1'}).then(null, function() { 
      return $.when('string1Default');//inject default on ajax failure 
     }); 
     var promise2 = $.ajax({url: 'url2'}).then(null, function() { 
      return $.when('string2Default');//inject default on ajax failure 
     }); 
     var promise3 = $.ajax({url: 'url3'}).then(null, function() { 
      return $.when('string3Default');//inject default on ajax failure 
     }); 
     this.promise = $.when(promise1, promise2, promise3).then(function (str1, str2, str3) { 
      return { 
       'string1': str1, 
       'string2': str2, 
       'string3': str3 
      }; 
     }); 
    }, 
    getStrings: function() { 
     if(!this.promise) { 
      this.initialize();//safety, in case initialize() has not been called 
     } 
     return this.promise; 
    } 
} 

А вот как назвать myObj.getStrings():

myObj.getStrings().then(function(stringsObject) { 
    // do stuff with stringsObject here. 
    console.dir(stringsObject); 
});