Tyler Murry
Tyler Murry

Reputation: 2815

Synchronous AngularJS $http Call

I have an service in my Angular app that is responsible for authorizing the user and returning the auth token back.

However, due to the async nature of $http, I cannot properly isolate the logic of my service. Instead I must return a promise and push the logic of interpreting the response to the caller of the service (single responsibility red flag).

Given this, it's made me reconsider whether I am thinking about this correctly. I come from a Java world where the majority of interactions are synchronous, so something isn't sitting well with me as I try to architect a clean design with single responsibility.

What am I missing here?

UPDATE I realize the below will not work as intended, but that's my thought of how I'd like it to work at least:

app.service('AuthenticationService', ['$http', '$httpParamSerializerJQLike', function($http, $httpParamSerializerJQLike)
{
    this.authServerBaseURL = "...";
    this.clientId = "...";

    this.authenticate = function(username, password)
    {
        var config =
        {
            headers:
            {
                "Content-Type"  : 'application/x-www-form-urlencoded',
                "Authorization" : "Basic " + btoa(this.clientId + ":")
            }
        }

        var body = $httpParamSerializerJQLike(
        {
            grant_type : "password",
            username : username,
            password : password
        });

        return $http.post(this.authServerBaseURL + '/oauth/token', body, config).
            success(function(data, status, headers, config)
            {               
                return data.access_token;
            }).
            error(function(data, status, headers, config)
            {
                return false;
            });    
    }

}]);

Upvotes: 0

Views: 1209

Answers (1)

Matsemann
Matsemann

Reputation: 21844

Update after you added code: Your thought process can work, see below. However, $http docs say not to use .success and .error. If you instead use .then, as in my examples below, it will work.

Assuming your code is something similar to this:

// AuthService
this.authenticate = function() {
    return $http.post('http://example.com', body, config);
}

// Using it:
AuthService.authenticate().then(function(data) {
    var token = data.access_token;
});

You can move the knowledge about how the data is extracted to the service like this:

// AuthService
this.authenticate = function() {
    return $http.post('http://example.com', body, config).then(function(data) {
        return data.access_token;
    });
}

// Using it:
AuthService.authenticate().then(function(token) {
    var token = token;
});

what happens here is that you make a new promise by calling .then on the $http promise, which is what is returned. The promises are chained, so the $http promise will resolve this new promise, which then resolves itself with the extracted token.

Upvotes: 2

Related Questions