0

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?

1
  • Everyone says return a promise! Angular 2 incorporates RxJS (Reactive Extensions). Angular 1 you have to do it yourself, but the idea is the same. It's the Observer => Observable pattern that you must learn. Commented Aug 1, 2016 at 13:42

4 Answers 4

1

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) {
            console.log(yourParameter);
            return $http.get('Home/GetSalesData')
                .then(function (result) {
                return result.data;
            });
        }
    };
});

and then :

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

var response = DataService.GetChartSelections('only pie one')
    .then(function(res) {
       // execute when you have the data
    })
    .catch(function(err) {
      // execute if you have an error in your http call
    });
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! This is precisely what I was looking for. It works service and Controller works async and the response actually provides the data as expected.
I know it wasn't an initial part of my question, but extending just a bit on your answer; how would one pass a parameter to the same service using this model??
Excellent, thanks for that. The variable was getting passed appropriately to the service but the $http call wasn't passing the variable to the method. Took a little to figure that part out but works great now. Thanks again ;-)
0

You should proceed like this :

DataService.GetChartSelections().then(function (data) {
     workWithData(data);
}

Actually $http.get returns a Promise. You can call the method then to handle the success or failure of your Promise

Comments

0

Should it not be like this, when your $http returns a promise or you pass a callback.

With passing callback as a param.

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

Controller code:

InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections(workWithData);

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

Or use then or success:

var response = DataService.GetChartSelections().then(function(res){
      //you have your response here... which you can pass to workWithData
});

Comments

0

Return the promise to the controller, dont resolve it in the factory

    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');
            }
        };
    });

In the controller,

var successCallBk =function (response){
    // Do Something with Data
};
var errorCallBK =function (response){
    // Error Module
};

var response = DataService.GetChartSelections().then(successCallBk,errorCallBK);

2 Comments

Your code example seems to ensure async execution but the response is an http status code of OK. It does not contain the data. Any ideas?
you must use response.data to get data

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.