2014-09-02 3 views
4

Я геокодирую некоторые адреса, иногда некоторые из них терпят неудачу. Я хотел бы получить остальные результаты и проигнорировать неудачный, чтобы отобразить другие координаты на карте. В настоящее время $ q.all будет вызывать errorHandler, когда его отклоняют, поэтому я теряю результаты других обещаний.

 $q.all(promises).then(function(coords) { 
      for (var j = 0;j<coords.length;j+=1) { 
       //success code 
      } 
     }, function(error) { 
     console.log("Failed",error.type,error.message); 
     }); 
+0

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

ответ

0

Что вы хотите, это q.allSettled, который не применяется в угловых условиях.

Вот relevant GitHub issue с просьбой о его реализации.

А вот one possible implementation, называется allComplete, что вы можете добавить в свое угловое приложение:

angular.module('App.services', ['ngResource']) 
    .config(function($provide) { 
    $provide.decorator("$q", ["$delegate", function($delegate) { 
     var $q = $delegate; 

     $q.allComplete = function(promises) { 

     if(!angular.isArray(promises)) { 
      throw Error("$q.allComplete only accepts an array."); 
     } 

     var deferred = $q.defer(); 
     var passed = 0; 
     var failed = 0; 
     var responses = []; 

     angular.forEach(promises, function (promise, index) { 
      promise 
      .then(function(result) { 
       console.info('done', result); 
       passed++; 
       responses.push(result); 
      }) 
      .catch(function(result) { 
       console.error('err', result); 
       failed++; 
       responses.push(result); 
      }) 
      .finally(function() { 
       if((passed + failed) == promises.length) { 
       console.log("COMPLETE: " + "passed = " + passed + ", failed = " + failed); 

       if(failed > 0) { 
        deferred.reject(responses); 
       } else { 
        deferred.resolve(responses); 
       } 
       } 
      }) 
      ; 
     }); 

     return deferred.promise; 

     }; 

     return $q; 
    }]); 
    }) 
; 
+0

Похоже, у него довольно большая ошибка - порядок обещаний в ответе не гарантируется. Разумеется, вы имеете в виду 'response [index] = result', а не' response.push (result) 'right? –

+8

Понятие «Я только что написал код, и я понятия не имею, как это работает» мне страшно. Извините, но если вы разместите здесь свой код, и если есть неправильные вещи, исправьте их. –

9

Решения было предложено Interrobang хорошо (минус ошибка), но если вы не любите, имеющие декоратор влияют каждое обещание в вашем коде, вы можете получить что-то похожее на allSettled как это вместо:

var suppress = function(x) { return x.catch(function(){}); } 
$q.all(promises.map(suppress)).then(function(coords) { 
    for (var j = 0; j < coords.length ; j+=1) { 
      //coords[j] contains the coords on success or is undefined on failure 
     } 
}); 
+0

Мне не нравится семантика, поэтому было бы неплохо увидеть более чистую версию. Но мне нравится простота, плюс это фактически решает проблему, как указано.+1 –

+0

Я не уверен, как семантика может быть лучше здесь - это уродливое решение, похожее на печально известное «поймать все», которое говорит «подавлять все, что может пойти не так» - если сетевой запрос не работал (но на сервере могут быть координаты), в этом коде не было бы способа справиться. Этот код решает очень узкую форму проблемы «урегулирования» - он будет работать в случае OP, и это довольно просто, но в общем случае «оседания» массива обещаний не будет работать очень хорошо. –

0

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

Давайте использовать пример, скажем, что у вас есть четыре асинхронных вызовов и каждый вызов функции конечной точки с контролем авторизации, если пользователь не имеет все разрешения на вызов происходит сбой

function getAllCatalogs() { 
     return $q.all([ 
      $http.get(baseUrl + 'equipment-design/'), 
      $http.get(baseUrl + 'engines-design/'), 
      $http.get(baseUrl + 'suspension-design/'), 
      $http.get(baseUrl + 'artifacts-design/') 
     ]).then(function (data) { 
      return data; 
     }); 
    } 

Due до $ q.всего нужно, чтобы все обещания заканчивались удовлетворительно, если один из предыдущих вызовов завершился неудачей из-за того, что пользователь не имеет разрешений, что весь вызов будет терпеть неудачу, но, возможно, вас интересует, когда вызов не дает просто вернуть пустой массив или объект по умолчанию, поэтому вам нужно обработать это поведение для себя, для этого вам нужно создать функцию, которая отвечает за вызов $ http.get обслуживать и управлять тем, как обещание будет возвращено после отказа или успеха вызова, в этом примере давайте назовем эту функцию getCatalogPromise и в ее параметрах будет URL-адрес службы, код будет:

function getCatalogPromise(url) { 
     var deferred = $q.defer(); 

     $http.get(url).then(function (response) { 
      deferred.resolve(response) 
     }, function() { 
      deferred.resolve([]); 
     }) 

     return deferred.promise; 
    } 

    function getAllCatalogs() { 

     return $q.all([ 
      getCatalogPromise(baseUrl + 'equipment-design/'), 
      getCatalogPromise(baseUrl + 'engines-design/'), 
      getCatalogPromise(baseUrl + 'suspension-design/'), 
      getCatalogPromise(baseUrl + 'artifacts-design/') 
     ]).then(function (data) { 
      return data; 
     }); 
    } 

, если вы обратите внимание на код getCatalogPromise это does'n важно, что обратный вызов к службе нашей отсроченной всегда будет в состоянии разрешить и это то, что $ q.all хотят, единственная разница заключается в том, что если сбой службы, мы возвращаем пустой массив.

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