2015-07-29 11 views
7

I modelli di utilizzo delle promesse mi confondono ancora.AngularJS: il metodo booleano del servizio dovrebbe restituire la promessa che si risolve in true/false o che viene risolto/rifiutato?

Ad esempio, nell'applicazione Angolare, ho un servizio usersService con il metodo emailExists(email). Ovviamente, esegue una richiesta al server per verificare se l'e-mail fornita esiste già.

Mi sembra naturale che il metodo emailExists(email) restituisca la promessa che durante il normale funzionamento si risolva in true o false. Se solo abbiamo qualche errore imprevisto (ad esempio, server ha restituito 500: internal server error, quindi promessa deve essere respinto, ma durante il normale funzionamento, si decise di corrispondente valore booleano.

Hovewer, quando ho iniziato ad attuare il mio asincrona direttiva validatore (da $asyncValidators), vedo che vuole risolto/promessa respinto così, ormai, ho finito con questo piuttosto brutta codice:.

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

})(); 

mi fa pensare che dovrei modificare il mio servizio in modo che restituisca risolto/rifiutata prometto invece, ma mi sembra una specie di innaturale per me: secondo me, la promessa respinta significa "non possiamo ottenere risultato ", non" risultato negativo ".

Oppure, ho frainteso l'utilizzo della promessa?

Oppure, devo fornire due metodi? Qual è lo schema comune per nominarli?

Qualsiasi aiuto è apprezzato.

+0

Il design della '$ asyncValidators' sembra essere incasinato quando si aspetta eccezioni. – Bergi

+0

Vedere anche [Quando rifiutare/risolvere una promessa] (http://stackoverflow.com/q/17293546/1048572) e [Perché le eccezioni sono utilizzate per rifiutare le promesse in JS?] (Http://stackoverflow.com/q/21616432/1048 mila cinquecentosettantadue). I rifiuti dovrebbero essere eccezionali. – Bergi

+0

I rifiuti di promessa sono eccezioni, la regola d'oro è usare le promesse dove mai usereste le eccezioni nel codice sincrono. Usereste eccezioni se il codice fosse completamente sincrono e IO fosse istantaneo? Se dovessi usare i rifiuti, altrimenti usa i valori. –

risposta

2

In questo caso non esiste un approccio corretto/errato a questo problema. Quello che dici del tuo servizio di controllo delle email sembra ragionevole: infatti, l'esistenza dell'email nel database non denota strettamente uno scenario di fallimento, il rifiuto di promessa solitamente corrisponde e riflette.

D'altro canto, anche il modo in cui Angular ha implementato i propri validatori asincroni ha senso, se ci pensate. Il risultato della convalida non riuscita sembra concettualmente un fallimento, non in termini di HTTP, ma nel senso della logica aziendale.

Quindi in questo caso probabilmente andrei a regolare il mio servizio personalizzato per restituire almeno lo stato non riuscito, come 409 Conflict.

Se avete ancora voglia di tornare 200 codice di successo insieme a vero/falso resonses si può ancora fare il codice validatore un po 'meno brutto:

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

Grazie. Anche se stavo pensando di restituire email_exists? $ q.reject(): $ q.when(); ', Mi piace la tua variante' $ q [email_exists? 'when': 'reject'](); 'altro. –

+1

Tuttavia, "convalida non riuscita" ("input non valido") non è uguale a "mancata convalida" ("nessuna convalida disponibile"). Angolare sembra perdere questa distinzione. – Bergi

+0

Sono d'accordo, tuttavia Angular ha scelto di andare in questo modo che ha permesso loro di avere un codice "elegante" per la convalida asincrona (controllare [qui] (https://github.com/angular/angular.js/blob/91b602263b96b6fce1331208462e18eb647f4d60/src/ng /directive/ngModel.js#L606)). Immagino che altrimenti avrebbero dovuto gestirlo come [questo] (http://jsfiddle.net/agrc28pz/). Immagino che istruire il servizio debba restituire valori di verità/falsità per i validatori asincroni che non si sentono abbastanza interessanti, così sono andati con promesse risolte/rifiutate per indicare il risultato della convalida. – dfsq