Mark Mark - 4 months ago 8
AngularJS Question

Angular Service working synchronously with Controller

I'm fairly new to AngularJS and have just begun to grasp many of the concepts I especially like the MVC design pattern. But I am having a difficult time implementing the Service layer in my application.

What I am finding is that after my Controller calls a method within the service, it continues with code execution before the service returns the data; so that by the time the service does return the data, it isn't of any use to the controller.

To give a better example of what I'm saying, here is the code:

var InsightApp = angular.module('InsightApp', ['chart.js']);

// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});

InsightApp.controller("ChartSelectionController", GetAvailableCharts);

// 2nd Controller calls the Service
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections();

// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}


All the examples I've found seem to be constructed as I have here or some slight variation; so I am not certain what I should be doing to ensure asynchronous execution.

In the Javascript world, I'd move the service to the inside of the Controller to make certain it executes async; but I don't how to make that happen in Angular. Also, it would be counter intuitive against the angular injection to do that anyway.

So what is the proper way to do this?

Answer

http return a promise not the data, so in your factory your returning the $http promise and can use it like a promise with then, catch, finally method.

see: http://blog.ninja-squad.com/2015/05/28/angularjs-promises/

InsightApp.controller("DataController", function($scope, $http, DataService){

var response = DataService.GetChartSelections()
    .then(function(res) {
       // execute when you have the data
    })
    .catch(function(err) {
      // execute if you have an error in your http call
    });

EDIT pass params to model service:

InsightApp.factory("DataService", function ($http) {
return {
    GetChartSelections: function (yourParameter) {
            return $http.get('Home/GetSalesData')
                .then(function (result) {
                return result.data;
            });
        }
    };
});

and then :

InsightApp.controller("DataController", function($scope, $http, DataService){

var yourParameter = 'only pie one';
var response = DataService.GetChartSelections(yourParameter)
    .then(function(res) {
       // execute when you have the data
    })
    .catch(function(err) {
      // execute if you have an error in your http call
    });
Comments