The patterns of promises usage still confuse me.
For example, in Angular application, I have a service usersService
with method emailExists(email)
. Obviously, it performs request to the server to check whether given email already exists.
It feels natural for me to make the method emailExists(email)
to return promise that in normal operation resolves to either true
or false
. If only we have some unexpected error (say, server returned 500: internal server error
, then promise should be rejected, but in normal operation, it is resolved to corresponding boolean value.
Hovewer, when I started implementing my async validator directive (by $asyncValidators
), I see that it wants resolved/rejected promise. So, by now, I ended up with this rather ugly code:
'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();
}
}
);
};
}
}
};
})();
It makes me think that I should modify my service so that it returns resolved/rejected promise instead. But, it feels a kind of unnatural for me: in my opinion, rejected promise means "we can't get result", not "negative result".
Or, do I misunderstand the promise usage?
Or, should I provide two methods? What is the common pattern to name them?
Any help is appreciated.
In this case there is no correct/incorrect approach to this problem. What you are saying about your email check service sounds resonable: in fact, existence of the email in database is not strictly denotes a failure scenario, promise rejection usually corresponds to and reflects.
On the other hand, the way Angular implemented their async validators also makes sense, if you think about it. Failed validation result conceptually feels like a failure, not in terms of HTTP, but in sense of business logic.
So in this case I would probably go and adjust my custom service to at least return non-success status, like 409 Conflict.
If you still want to return 200 success code along with true/false resonses you can still make validator code a little bit less ugly:
ngModel.$asyncValidators.emailExists = function (modelValue, viewValue) {
return usersService.emailExists(viewValue).then(function (email_exists) {
return $q[email_exists ? 'when' : 'reject']();
});
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With