Jordy van Eijk
Jordy van Eijk

Reputation: 2766

AngularJS Service returning data instead of promise

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?

Upvotes: 2

Views: 1511

Answers (4)

user1364910
user1364910

Reputation:

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

Upvotes: 2

Andy Gaskell
Andy Gaskell

Reputation: 31761

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.

Upvotes: 1

Moshe Shaham
Moshe Shaham

Reputation: 15984

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

Upvotes: 2

Himanshu Arora
Himanshu Arora

Reputation: 2578

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!

Upvotes: 0

Related Questions