2

I have a question conserning the use of services or factories inside an AngularJS application.

I Want to write a service that will return data from an Api which i can use inside my controllers.

Lets say i want to have a call like $scope.people = myPeopleService.getPeople(); and inside my service want to check if i already have people and return those otherwise i want to do a $http.get() and fill the people inside my service and then return them. I do not want to have .then inside my controller. Is this even possible?

3
  • You need some kind of promise, in case of that http call, it'll be async. Commented Jul 13, 2015 at 13:43
  • @tymeJV i understand that i need some kind of promise but itn't it possible to handle all the promises inside the service? Commented Jul 13, 2015 at 13:46
  • I dont think so, your controller needs to resolve everything in the end, else it'll try to execute the next line before the data comes back. You can handle a bulk of the work in the service. Commented Jul 13, 2015 at 13:48

4 Answers 4

2

If you dont want to return the promise to the consumer of your service:

.service('...', function ($http) {
  var cachedResponse;

  this.getStuff = function () {
    if (cachedResponse) {
      return cachedResponse;
    }

    return $http.get('someUrl')
      .then(function (response) {
        cachedResponse = response;
        return response; // Return the response of your $http call. 
      });
  };
});
Sign up to request clarification or add additional context in comments.

1 Comment

Won't $http.get() return a promise immediately?
2

My solution is to return a reference to an object that might be empty at first, but will hold the data eventually:

app.factory('myPeopleService', function($http){

    var people = {};

    $http
        .post( "/api/PeopleService/getInitData", {
        }).success(function (data, status, headers, config) {
            angular.extend(people, data);
        }).error(function (data, status, headers, config) {
        });

    return {
        getPeople: function () {
            return people;
        }
    };
});

the key is to use angular.extend in order to preserve the object reference.

in the controller you can use ng-show until the data is fulfilled, and/or use watch for processing

Comments

1

You won't be able to escape that at some level, somewhere, this call is asynchronous. One part of your question is easy, caching data is just an option in the $http call:

$http.get(url, {cache: true})

If you expose this call from a service only one call will be made over the network, no changes are required in your controller code.

Another thing to look into is using your router's resolve feature (ui-router and the vanilla router both support resolve). This can clean up some of the code in your controller.

Comments

0

It is not possible to do it without a .then in your use case. Since you want to make use of $http to fetch the people and return them (if they were not present already). $http works asynchronously and would return a promise. Due to the asynchronous behavior of $http it becomes mandatory to handle the promise returned in the calling function.

Hope this helps!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.