2014-09-13 69 views
0

我對AngularJS相對較新,並開始嘗試使用AngularJS 1.3中提供的新asyncValidators,並且非常喜歡我所看到的。但是,我有一個問題,關於如何處理來自服務器的非快樂路徑錯誤。如何使用AngularJS asyncValidators處理來自服務器的意外響應?

使用asyncValidators時,您返回一個承諾,這是有道理的。假設我們有一個驗證器,詢問服務器是否有一個productId。調用REST api,如果響應返回爲200,則productId有效。如果響應返回爲404,則productId無效。

處理響應(如500或服務器超時)的最佳方法是什麼?如果我返回promise.resolve,那麼它會告訴formId是有效的(我們不知道)。如果我返回promise.reject,它會告訴formId無效(我們不知道)。我想我會變得可愛並且回覆一個空的承諾(return $q.defer().promise;),但是這留下了形式爲$pending等待承諾決議永遠不會發生。

我已經在下面包含了一個快速代碼示例來演示。如果我對此採取完全倒退的做法,我很樂意提供任何建議。

app.directive('isValidProductId', ['$http', '$q', 'productService', function ($http, $q, productService) { 
    return { 
     restrict: 'A', 
     require: 'ngModel', 
     link: function (scope, elem, attrs, ctrl) { 

      ctrl.$asyncValidators.valid = function (modelValue, viewValue) { 
       var value = modelValue || viewValue; 
       var deferred = $q.defer(); 

       var result = productService.getProduct(value).then(function (data) { 
        deferred.resolve(data); 
       }, 
       function (error) { 
        if (error.status == 404) { 
         // The productId is invalid 
         deferred.reject(error); 
        } else { 
         // *** What to do if the response is 500, for example?? *** 
        } 
       }); 

       return deferred.promise; 
      } 
     } 
    } 
}]) 

回答

0

如果您收到500錯誤,那麼您可以將響應視爲當前驗證密鑰的有效性,但將另一個驗證密鑰設置爲無效。所以,通過使用$ http來保持這個答案非常通用,下面的內容應該可以工作。

ngModelController.$asyncValidators.valid = function(modelValue, viewValue) { 
    // Make sure to reset the error state from any previous error 
    ngModelController.$setValidity('connectionError', true); 

    return $http(...).catch(function(error) { 
    if (error.status == 500) { 
     ngModelController.$setValidity('connectionError', false); 
    } else { 
     return $q.reject(); 
    } 
    }); 
}); 

然後,您可以在模板或控制器中使用密鑰connectionError來顯示相應的消息。

+0

感謝米哈爾 - 這些似乎是一種合理的模式。 – 2014-09-16 01:23:08