2015-07-29 11 views
7

Wzorce wykorzystania obietnic wciąż mnie mylą.AngularJS: Czy metoda boolowska serwisu powinna przybiec obietnicę, która rozwiąże wartość true/false, lub zostanie rozwiązana/odrzucona?

Na przykład w aplikacji Angular mam usługę usersService z metodą emailExists(email). Oczywiście, wykonuje żądanie do serwera, aby sprawdzić, czy podany adres e-mail już istnieje.

To dla mnie naturalne, że metoda emailExists(email) zwróciła obietnicę, że w normalnej pracy rozwiąże się z true lub false. Jeśli tylko mamy jakiś nieoczekiwany błąd (powiedzmy, serwer zwrócił 500: internal server error, to obietnica powinna zostać odrzucona, ale w normalnej pracy, uchwala się co odpowiada wartość logiczną.

Hovewer, kiedy rozpoczęła realizację mojego dyrektywę validator asynchronicznej (przez $asyncValidators), widzę, że chce rozwiązać/odrzucone obietnica więc teraz, skończyło się z tym kodem raczej brzydki.

'use strict'; 

(function(){ 

    angular.module('users') 
    .directive('emailExistsValidator', emailExistsValidator); 


    emailExistsValidator.$inject = [ '$q', 'usersService' ]; 
    function emailExistsValidator($q, usersService){ 
     return { 
     require: 'ngModel', 
     link : function(scope, element, attrs, ngModel) { 

      ngModel.$asyncValidators.emailExists = function(modelValue, viewValue){ 
       return usersService.emailExists(viewValue) 
       .then(
        function(email_exists) { 
        // instead of just returning !email_exists, 
        // we have to perform conversion from true/false 
        // to resolved/rejected promise 
        if (!email_exists){ 
         //-- email does not exist, so, return resolved promise 
         return $q.when(); 
        } else { 
         //-- email already exists, so, return rejected promise 
         return $q.reject(); 
        } 
        } 
       ); 
      }; 
     } 
     } 
    }; 

})(); 

to sprawia, że ​​myślę, że należy zmodyfikować moją usługę tak, że zwraca rozwiązany/odrzucone obiecuję zamiast tego, ale wydaje mi się to nienaturalne: w mojej opinii odrzucona obietnica oznacza "nie możemy uzyskać wyniku ", a nie" wynik ujemny ".

Czy też nie rozumiem użycia obietnicy?

Czy powinienem podać dwie metody? Jaki jest wspólny wzorzec, aby je nazwać?

Każda pomoc jest doceniana.

+0

Konstrukcja '$ asyncValidators' wydaje się być pomieszane kiedy oczekuje wyjątków. – Bergi

+0

Zobacz także [Kiedy odrzucić/rozwiązać obietnicę] (http://stackoverflow.com/q/17293546/1048572) i [Dlaczego wyjątki są używane do odrzucania obietnic w JS?] (Http://stackoverflow.com/q/21616432/1048572). Odrzucenia powinny być wyjątkowe. – Bergi

+0

Obietnice odrzucenia są wyjątkami, złotą zasadą jest używanie obietnic, w których kiedykolwiek używasz wyjątków w kodzie synchronicznym. Czy używałbyś wyjątków, gdyby kod był całkowicie zsynchronizowany, a IO było natychmiastowe? Jeśli chcesz użyć odrzucenia, w przeciwnym razie użyj wartości. –

Odpowiedz

2

W tym przypadku nie ma poprawnego/niepoprawnego podejścia do tego problemu. To, co mówisz o usługach sprawdzania poczty e-mail brzmi rozsądnie: w rzeczywistości istnienie wiadomości e-mail w bazie danych nie oznacza ściśle scenariusza awarii, obietnica odrzucenia zwykle odpowiada i odzwierciedla.

Z drugiej strony sposób, w jaki Angular implementował swoje walidatory asynchroniczne, ma również sens, jeśli się nad tym zastanowić. Wynik niepowodzenia sprawdzania poprawności koncepcyjnie jest jak porażka, nie w kontekście HTTP, ale w sensie logiki biznesowej.

W takim przypadku prawdopodobnie dostosowałbym moją usługę niestandardową, aby przywrócić status braku sukcesu, np. 409 Conflict.

Jeśli nadal chcesz, aby powrócić 200 kod sukcesu wraz z prawda/fałsz resonses można jeszcze wprowadzić kod walidator trochę mniej brzydki:

ngModel.$asyncValidators.emailExists = function (modelValue, viewValue) { 
    return usersService.emailExists(viewValue).then(function (email_exists) { 
     return $q[email_exists ? 'when' : 'reject'](); 
    }); 
}; 
+0

Dzięki. Chociaż myślałem o "powrocie email_istniejących? $ q.reject(): $ q.when(); ', podoba mi się Twój wariant' $ q [email_exists? "when": "reject"](); "więcej. –

+1

Jednak "niepowodzenie sprawdzania poprawności" ("nieprawidłowe dane wejściowe") nie jest tym samym, co "niepowodzenie sprawdzania poprawności" ("brak sprawdzania poprawności"). Angular wydaje się tęsknić za tym rozróżnieniem. – Bergi

+0

Zgadzam się, jednak Angular wybrał tę drogę, która pozwoliła im mieć "elegancki" kod do sprawdzania asynchronizacji (sprawdź [tutaj] (https://github.com/angular/angular.js/blob/91b602263b96b6fce1331208462e18eb647f4d60/src/ng /directive/ngModel.js#L606)). Wyobrażam sobie, że w przeciwnym razie musieliby sobie z tym poradzić, coś w stylu [this] (http://jsfiddle.net/agrc28pz/). Domyślam się, że usługa musi zwracać wartości truey/falsy, ponieważ walidatory async nie czują się wystarczająco cool, więc poszły z rozwiązanymi/odrzuconymi obietnicami, aby wskazać wynik walidacji. – dfsq

Powiązane problemy