ocket-san
ocket-san

Reputation: 884

asynchronous calls in angularjs

I have a couple of questions on asynchronous functions in angular. I want my service function to be able to return data I get by using $http and use that data in another function. Let me demonstrate with the current code:

dashboard.servicesModule.service('SubscriptionService', function ($http, $q) {

    this.getImportantData= function (param1, param2) {

        var url = "my/url/with/parameters?param1=param1&param2=param2";     

        $http.get(url).then(function(response){         
            console.log("response");
            console.log(response.data); // < --- this actually shows the data i need!!          
            return response.data.vsyData; <--- however, this returns undefined
        }, function(error){
            // some error thingy just in case
        });

    };

    this.getSomeFunctionality = function(param1, param2, param3){
        var importantdata= this.getImportantData(param1, param2);

        // do some filtering on the data with the purpose of returning only what i need

        console.log(importantdata); <--- undefined

    };

    this.getEvenMoreFunctionality = function(param1, param2, param3){
        var importantdata= this.getImportantData(param1, param2);

        // reusing getImportantData again! 

        console.log(importantdata); <--- undefined

    };
});

So I have been trying all kinds of things ( like this and this ) and some inventions of my own. But it starts to seem like there is no way of using the data from the $http.get anywhere else then in its own callback. And since i need the endresult in my controller, it seems like there is no other way then perform the $http.get(url).success(...some logic here) in my controller and do the filtering and other manipulation there.

However, I read here and I quote:

Our controller should be almost completely agnostic as to how data is retrieved and sent, and should only be concerned with the general action of sending and retrieving data to and from the service.

I interpret this as following: my controller should ask the service for the data I need and the service should make sure that it gives the data in the correct form.

The most important question is: how can I make the above code do what it needs to do or would that be impossible?

And am I supposed to do my business logic in my controller? Because here, in the angular docs I basically read that you should do business logic in your controller, but not filtering...

Its probably obvious, but ... I am an angular newbie :-). Thanks!

Upvotes: 1

Views: 5366

Answers (3)

asdfg
asdfg

Reputation: 1

function getSomething(){
var deferred = $q.defer();
$http.get('foo/bar')
    .success(function(data){
        $deferred.resolve(data);
    });
return deferred.promise();
}
  getSomething().then(function(data){
   console.log(data);
});

Upvotes: 0

lenilsondc
lenilsondc

Reputation: 9800

For an assyncronous request you cannot make imediate return statement, tha main javascript thread will not wait for request resolution. I really recomend use $q API, is the angular implementation of Kris Kowal's Q promises/deferred systems.

function getSomething(){
    var deferred = $q.defer();
    $http.get('foo/bar')
        .success(function(data){
            $deferred.resolve(data);
        });
    return deferred.promise();
}

getSomething().then(function(data){
    console.log(data);
});

Or you can return directly the $http promise. In case you want to remove the .then() from your controller, you can use $routeProvider with the resolve option that supports $q promises and create routes that self resolve your data, so you just inject them in controller, free of the $q proceedings.

UPDATE 1 - Practical example of resolving dependencies in routes

$routeProvider.when('/items/list', {
    templateUrl: '/templates/item/list',
    controller: 'ListItemsCtrl',
    resolve: {
      items: function(ItemsService) {
        return ItemsService.getItems(); // getItems returns a promise like 'return $http.get('/items');'
      }
    }
  });

//controller
function ListItemsCtrl($scope, items){
    //do something with your items
}

Upvotes: 2

Niezborala
Niezborala

Reputation: 1857

Try this:

this.getImportantData= function (param1, param2) {
    var url = "my/url/with/parameters?param1=param1&param2=param2";     

    return $http.get(url);
};

this.getSomeFunctionality = function(param1, param2, param3){
    this.getImportantData(param1, param2)
    .then(function(response){         
        console.log(response.data.vsyData);
    }, function(error){
        // some error thingy just in case
    });
};

this.getEvenMoreFunctionality = function(param1, param2, param3){
    this.getImportantData(param1, param2)
    .then(function(response){         
        console.log(response.data.vsyData);
    }, function(error){
        // some error thingy just in case
    });
};

You can't get data from a method which has an asynchronous call. You can return promise, and then you can get data from promise.

Upvotes: 4

Related Questions