devwannabe
devwannabe

Reputation: 3210

convert to promise to solve async nature of http

On my login screen, it calls login function when I click the "Sign-In" button. It's actually ng-submit="login()". The code is in my LoginCtrl controller.

 function onSuccessfulLogin() {
    $scope.failureMessage  = "";
    $rootScope.mainbody.position = 'absolute';

    if (nextState !== null && typeof nextState.name === 'string' && nextState.name !== '') {
        console.log("calling nextState ......");
        $state.go(nextState.name, nextState.params);
    } else {
        $state.go('main', {});
    }
}

$scope.login = function() {
    disableLoginButton();

    $rootScope.login = {
        goodmsg : true,
        errormsg : false
    }

    $scope.failureMessage  = "Signing in Analytics Dashboard ....";
    User.authenticate($scope.username, $scope.password, onSuccessfulLogin, onFailedLogin, $scope.persist);
};

I have a service called User and I call the "authenticate" function once I click the sign-in button above. It's currently working fine until I added more HTTP calls inside "this.authenticate" function. What I'd like to happen is convert this to promise so that it will call onSuccessfulLogin() at the right time, when all the data from all HTTP requests have been received. However, I'm not sure how I will convert "this.authenticate" to return a promise. Btw, TokenService is a Restangular factory that I made.

Also, the reason I wanted to convert it as a promise is because I wanted to make sure all data is ready before ui-router instantiate the controller I'll be displaying.

this.authenticate = function(username, password, successCallback, errorCallback, persistData) {

    this.removeAuthentication();

    TokenService.setResponseInterceptor(function (data, operation, what, url, response) {
        if (operation == 'post') {
            $rootScope.locationResourceId = response.headers('Location').split('/')[response.headers('Location').split('/').length-1]
        }
        return response.data;
    });

    TokenService.one('authentokens').customPOST({'email' :  username , 'password' : password}, '', {app : 'baam'})
        .then(function(data) {
            var userresourceId = data.href.split('/')[data.href.split('/').length-1]

            $rootScope.userData = {
                isAuthenticated : true,
                username : username,
                bearerToken : data.token,
                expirationDate : new Date(data['expires']),
                resourceId : userresourceId,
                tokenResourceId : $rootScope.locationResourceId
            };

            TokenService.one('users').customGET($rootScope.userData.resourceId, { 'token' : $rootScope.userData.bearerToken })
                .then(function(jsondata) {
                    $rootScope.userData.locale = retrieveLocale();

                    // Set locale via Factory
                    var currentLocale = CurrentLocaleFactory;
                    currentLocale.locale = $rootScope.userData.locale;

                    $rootScope.userData.firstname = (jsondata.firstname == null) || (jsondata.firstname == null) ? '' : jsondata.firstname;
                    $rootScope.userData.lastname = (jsondata.lastname == null) || (jsondata.lastname == null) ? '' : jsondata.lastname;
                    var avatar = username.split('@')[0].toLowerCase();

                    $http.get('assets/json/avatar.json')
                    .then(function(res) {

                        $rootScope.userData.gravatarLink = res.data.gravatarLink;
                        if (persistData === true) {
                            saveData();
                        }
                        if (typeof successCallback === 'function') {
                            successCallback();
                        }
                    }, function() {
                        $rootScope.userData.gravatarLink = "assets/img/noface.png";
                        if (persistData === true) {
                            saveData();
                        }
                        if (typeof successCallback === 'function') {
                            successCallback();
                        }
                    })
            })
        }, function(data) {
            if (typeof errorCallback === 'function') {
                if (data.error_description) {
                    errorCallback(data.error_description);
                } else {
                    errorCallback(data.data.message);
                }
            }
        })
};

Upvotes: 0

Views: 113

Answers (1)

Mosho
Mosho

Reputation: 7078

Return the promises from the function:

 //First return
 return TokenService.one('authentokens').customPOST({
     'email': username,
     'password': password
 }, '', {
     app: 'baam'
 }).then(function(data) {
     /* ... */
     // Second return inside the success handler
     return TokenService.one('users').customGET($rootScope.userData
         .resourceId, {
             'token': $rootScope.userData.bearerToken
         }).then(function(jsondata) {
         /* ... */
     })
 })

Your function will then return a promise that will be resolved after both async calls have returned.

If ordering is not important, you can also use $q.all(arrayOfPromises), which returns a promise that will be resolved when all of the promises in the array have returned.

Upvotes: 1

Related Questions