2015-07-29 2 views
7

Die Muster der Verwendung von Versprechungen verwirren mich immer noch.AngularJS: Sollte die boolesche Methode von service die Antwort zurückgeben, die zu wahr/falsch aufgelöst wird, oder die gelöst/zurückgewiesen wird?

Zum Beispiel habe ich in Angular-Anwendung einen Service usersService mit Methode emailExists(email). Offensichtlich führt es eine Anfrage an den Server durch, um zu überprüfen, ob eine gegebene Email bereits existiert.

Es fühlt sich natürlich für mich an, um die Methode emailExists(email) zur Rückkehr versprechen, dass im Normalbetrieb entweder true oder löst. Wenn wir nur etwas unerwarteten Fehler haben (zum Beispiel Server 500: internal server error zurückgegeben, dann sollten Versprechen abgelehnt werden, aber im Normalbetrieb, wird sie in entsprechenden Booleschen Wert aufgelöst.

Hovewer, wenn ich meine Asynchron-Validator Richtlinie begonnen Umsetzung (von $asyncValidators), ich sehe, dass es will aufgelöst/abgelehnt Versprechen also, jetzt, ich mit diesem ziemlich hässlich Code endete.

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

})(); 

es hat mich denken lässt, dass ich meinen Dienst ändern sollte, so dass es gelöst Rückkehr/abgelehnt Verspreche es stattdessen. Aber es fühlt sich für mich irgendwie unnatürlich an: Meiner Meinung nach bedeutet das abgelehnte Versprechen "wir können kein Ergebnis bekommen ", nicht" negatives Ergebnis ".

Oder missverstehe ich die Verwendung von Versprechen?

Oder sollte ich zwei Methoden bereitstellen? Was ist das übliche Muster, um sie zu benennen?

Jede Hilfe wird geschätzt.

+0

Der Entwurf '$ asyncValidators' scheint verwirrt zu werden, wenn Es erwartet Ausnahmen. – Bergi

+0

Siehe auch [Wann ein Versprechen abzulehnen/aufzulösen] (http://stackoverflow.com/q/17293546/1048572) und [Warum werden Ausnahmen für die Ablehnung von Versprechen in JS verwendet?] (Http://stackoverflow.com/q/21616432/1048572). Ablehnungen sollten außergewöhnlich sein. – Bergi

+0

Versprechen zurückweisen sind Ausnahmen, die goldene Regel besteht darin, Versprechen zu verwenden, wo immer Sie Ausnahmen im synchronen Code verwenden. Würden Sie Ausnahmen verwenden, wenn der Code vollständig synchron ist und IO sofort ausgeführt wird? Wenn Sie Ablehnungen verwenden würden, verwenden Sie andernfalls Werte. –

Antwort

2

In diesem Fall gibt es keinen korrekten/falschen Ansatz für dieses Problem. Was Sie über Ihren E-Mail-Scheckdienst sagen, klingt vernünftig: Tatsächlich bedeutet das Vorhandensein der E-Mail in der Datenbank nicht unbedingt ein Fehlerszenario, die Ablehnung von Versprechen entspricht normalerweise und spiegelt wider.

Auf der anderen Seite macht die Art, wie Angular ihre Async-Validatoren implementiert, auch Sinn, wenn Sie darüber nachdenken. Fehlgeschlagene Validierungsergebnisse erscheinen konzeptionell als Fehler, nicht in Bezug auf HTTP, sondern im Sinne der Geschäftslogik.

Also in diesem Fall würde ich wahrscheinlich gehen und meinen benutzerdefinierten Service anpassen, um mindestens Nichterfolgsstatus, wie 409 Conflict.

Wenn Sie wollen immer noch 200 Erfolgscode zurück zusammen mit true/false resonses Sie können immer noch Validator Code ein bisschen weniger hässlich machen:

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

Danke. Obwohl ich an 'return email_exists 'dachte? $ q.reject(): $ q.when(); ', Ich mag deine Variante' $ q [email_exists? 'wann': 'ablehnen'](); 'mehr. –

+1

"Fehlgeschlagene Validierung" ("ungültige Eingabe") ist jedoch nicht identisch mit "fehlgeschlagener Validierung" ("keine Validierung verfügbar"). Angular scheint diese Unterscheidung zu verfehlen. – Bergi

+0

Ich stimme zu, aber Angular entschied sich dafür, diesen Weg zu gehen, was ihnen erlaubte, "eleganten" Code für Async-Validierung zu haben (siehe [hier] (https://github.com/angular/angular.js/blob/91b602263b96b6fce1331208462e18eb647f4d60/src/ng /directive/ngModel.js#L606)). Ich stelle mir vor, dass sie sonst etwas damit zu tun hätten (http://jsfiddle.net/agrc28pz/). Ich denke, dass die Anweisung, dass der Dienst truthy/falsy-Werte für asynchrone Validatoren zurückgeben muss, sich nicht cool genug anfühlte, so dass sie mit aufgelösten/abgelehnten Versprechen gingen, um das Validierungsergebnis anzuzeigen. – dfsq