2016-05-18 8 views
0

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

Это код, у меня есть, вырезать немного меньше, чтобы сделать его более ясным:

 // Central function that creates a Deferred object and returns a 
     // Promise from it. when the passed request is done, 
     // the Deferred is resolved 
     var getData = function(url, successFunction) { 
      var deferred = $.Deferred(); 
      $.ajax({ 
       url: url, 
       method: 'get', 
       dataType: 'json' 
      }).done(function(p) { 
       successFunction(p); 
       deferred.resolve(p); 
      }).fail(function(p){ 
       deferred.reject(p); 
      }); 
      return deferred.promise(); 
     }; 

     // Success actions to be called for each asynchronous request 

     var populateDestinations = function(data) { 
      // synchronous actions on DOM 
     }; 

     var populateTaxes = function(data) { 
      // synchronous actions on DOM 
     }; 

     var populatePayment = function(data) { 
      // synchronous actions on DOM 
     }; 


     // Actions that return a Promise to control the resolution of 
     // all the deferred objects 

     var getCustomerDestinations = function(customerId) { 
      var url = $modal.data('url_destinations') + customerId; 
      return getData(url, populateDestinations); 
     }; 

     var getCustomerTaxes = function(customerId) { 
      var url = $modal.data('url_taxes') + customerId; 
      return getData(url, populateTaxes); 
     }; 

     var getCustomerPayment = function(customerId) { 
      var url = $modal.data('url_payment') + customerId; 
      return getData(url, populatePayment); 
     }; 

     var populateFields = function() { 
      // final actions 
     }; 


     $.when(getCustomerDestinations(customer_id), 
       getCustomerTaxes(customer_id), 
       getCustomerPayment(customer_id)) 
     .done(function(){ 

      populateFields(); 

     }); 

populateFields() вызывается всякий раз, когда один из «обещанных» функций решена, а не когда все из них разрешены.

Любая идея, что я делаю неправильно? Возможно, я еще не понял концепцию объекта «Отсрочка».

+1

Вы не хватает закрывающая скобка в важных местах. Добавьте их (покажите нам код, который не является синтаксической ошибкой). – Bergi

+1

Избегайте [отложенного антипаттера] (http://stackoverflow.com/q/23803743/1048572)! Это должно быть просто 'function getData (url, fn) {return $.getJSON (URL) .then (п); } ' – Bergi

+1

На самом деле вам не нужно создавать отложенный объект, чтобы получить обещание, вместо этого просто верните' $ .ajax() ', который по умолчанию возвращает объект обещания. поэтому удалите все отложенные объекты и просто вернитесь из '$ .ajax()' – dreamweiver

ответ

2

Вам действительно не нужно использовать любые отложенные объекты для отслеживания вызовов ajax, вместо этого вы можете просто использовать объект обещания, возвращенный с $.ajax, в пределах $.when().

Jquery КОД:

var getData = function(url, successFunction) { 
     return $.ajax({ 
      url: url, 
      method: 'get', 
      dataType: 'json' 
     }).then(function(p) { 
      successFunction(p); 
     },function(p){ 
      //process error using error callback, 
      //just like success callbacks 
     }); 
    }; 

Приказываю обрабатывать отдельные Ajax вызовы, которые вы можете использовать .then() вместо .done() & .fail(), потому что они не будут возвращать любой объект обещание в отличие от .then() отслеживать то же самое в .when().

Остальная часть вашего кода будет работать так, как есть.

Что JQuery форум говорит:

По JQuery 1,8, метод deferred.then() возвращает новое обещание, которое может фильтровать статус и значение отложенных через функцию, заменив ныне устаревшим deferred.pipe() способ. Функции doneFilter и failFilter фильтруют исходные состояния и значения отложенных/отклоненных исходных отложенных. Функция progressFilter фильтрует любые вызовы с уведомлением оригинала отложенных уведомлений или уведомлений. Эти функции фильтра могут возвращать новое значение, которое должно быть передано в ответ на вызовы .done() или .fail(), или они могут возвращать другой наблюдаемый объект (отложенный, обещающий и т. Д.), Который передаст свои разрешенные/отклоненные статус и значения для обратных вызовов обещания.

refence ссылки:

+0

Вы должны всегда использовать 'then' вместо' done' и 'fail' (если вы не знаете, что вы делаете) – Bergi

+0

use is' then() 'это ничего, кроме использования' done' & 'fail' под ним, поэтому действительно не имеет значения. вот инструкция из jquery frorum для 'then', **" jqXHR.then(): Включает функциональные возможности методов .done() и .fail(), позволяя (как и jQuery 1.8) подставлять подлинные Promise Обратитесь к отложенному.then() для деталей реализации. ** ** – dreamweiver

+0

Это * делает * делает разницу (в возвращаемом значении), и именно поэтому ее следует использовать по умолчанию. 'then' больше, чем просто' done' и 'fail'. Вы должны привыкнуть к этому. – Bergi

Смежные вопросы