簡體   English   中英

當一個承諾被拒絕時,使$ q.all無聲地失敗

[英]Make $q.all fail silently when one promise is rejected

我正在對一些地址進行地理編碼,有時其中一些地址失敗。 我希望能夠得到剩下的結果並忽略失敗的結果,這樣我就可以在地圖上顯示其他坐標。 目前$ q.all將在拒絕一個時調用errorHandler,因此我將丟失其他promise的結果。

      $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);
      });

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
      }
});

你想要的是q.allSettled ,它沒有在Angular中實現。

這是一個請求其實現的相關GitHub問題

這里有一個可能的實現 ,名為allComplete ,您可以添加到Angular應用程序:

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;
    }]);
  })
;

您可以僅使用Angular的實現來解決您的問題,您必須做的是隔離其他函數中的異步調用,該函數將返回一個承諾,並且將為您管理此承諾。

讓我們舉一個例子,假設您有四個異步調用,並且每個函數都使用授權控制調用一個端點,如果用戶沒有所有權限,則調用將失敗

  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;
        });
    }

由於$ q.all需要所有承諾都能令人滿意地完成,如果之前的一個呼叫由於用戶沒有權限而失敗,則整個呼叫將失敗,但也許你感興趣的是當呼叫失敗時只返回一個空數組或默認對象,所以你必須自己處理這個行為,為了實現這一點,你必須創建一個函數,負責調用$ http.get服務並管理一旦調用后將如何返回promise失敗或成功,對於這個例子,讓我們調用該函數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的代碼,那么返回對服務的調用無關緊要,我們的延遲總是將處於解決狀態,這就是$ q.all想要的,唯一的區別是如果服務失敗我們返回一個空數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM