javauser javauser - 3 months ago 9
AngularJS Question

Angular function returned promise before http api completes

I am new in AngularJs.
I have one validate function which is returning promise. this function internally calls http get api and receives promise response. I have some validation code which require the response from the called api. but before http call completes and the function receive response from the api, validate function returned promise to the caller. which is causing validation failed. can someone please share some code which satisfy this requirement.

function validateDates(delegate) {
var currStartDate = delegate.start_date;
var currEndDate = delegate.end_date;
var overlap = false;
var deferred = $q.defer();

UserDelegateService.getDelegateForUser(delegate.comit_id).then(
function(res) {
for(var i = 0; i<res.length; i++) {
var sDate = $filter('date')(res[i].start_date, 'yyyy-MM-dd');
var eDate = $filter('date')(res[i].end_date, 'yyyy-MM-dd');
if(currStartDate <= eDate && sDate <= currEndDate) {
overlap = true;
deferred.resolve(overlap);
} else
deferred.reject("Not overlapping");
}
},
function(errorresponse) {
console.log(errorresponse);
});
return deferred.promise;
};


calling code :

$scope.saveDelegate = function() {
var delegate = {
//assign values ...
};

var promise = validateDates(delegate);
promise.then(function(data) {
if(data) {
console.log('Dates are overlapping....if part.......', data);
}
}, function(reason) {
console.log('Dates are not overlapping..saving datlegate..else part.........', reason);
$scope.save(delegate);
});
};

Answer

Using $q.defer breaks the promise chain and loses error information. Also the resolve/reject decision was being made on first item of the for loop.

Instead return values and chain.

function validateDates(delegate) {      
    var currStartDate = delegate.start_date;
    var currEndDate = delegate.end_date;
    //var overlap = false;
    //var deferred = $q.defer();

    var p = UserDelegateService.getDelegateForUser(delegate.comit_id);
    var derivedPromise = p.then(
        function onSuccess(res) {
            //Initialize overlap var in success handler
            var overlap = false; 
            for(var i = 0; i<res.length; i++) {
                var sDate = $filter('date')(res[i].start_date, 'yyyy-MM-dd');
                var eDate = $filter('date')(res[i].end_date, 'yyyy-MM-dd');
                if(currStartDate <= eDate && sDate <= currEndDate) {
                     overlap = true;         
                };
            //Return value of overlap for chaining
            return overlap;
        });
    };
    //return derived promise
    return derivedPromise;
};

The above function returns a promise that resolve true if any of the dates overlap and resolves false if none of the dates overlap.

Client code:

$scope.saveDelegate = function() {
    var delegate = {
            //assign values ... 
    };

    var promise = validateDates(delegate);
    promise.then(function onSuccess(overlap) {   
        if(overlap) {
            console.log('Dates are overlapping....if part.......', overlap);
        } else {
            console.log('Dates are not overlapping..saving datlegate..');
            $scope.save(delegate);
        };
    }).catch(function onReject(reason) {
        console.log("Promise rejected for another reason");
    });
};

By returning and chaining promises, any error in the getDelegateForUser operation gets forwarded to the client code.

Comments