2

I'm implementing a small service for my angularJS app that makes an http request to my server for a couple of text posts. Here's my current implementation:

app.factory("postFetcher", ['$http', function($http){
  var posts; 

  $http.get('https://cdn.contentful.com/spaces/k2mwszledbge/entries?access_token=afa8ba8572bb0232644d94c80cfd4ae01314cd0589b98551147aab50f7134e30')
    .then(function(response){
      posts = response.data.items;
    });

  return {
    getList: function(){
      return posts; 
    }
  }
}]);

The problem with this is that the http request is not complete by the time that the posts array is returned. My intuition tells me to place the return function within the http .then function so that it is only returned once the request is complete, however this isn't allowed.

Is there a way I can delay the return of posts until the http request is complete?

2 Answers 2

3

Use promise it's one way that I see:
Factory:

app.factory("postFetcher", ['$http', '$q', function($http, $q){
    var posts; 

    return {
        getList: getListFn
    };

    function getListFn(){
        var defer=$q.defer();

        $http.get('https://cdn.contentful.com/spaces/k2mwszledbge/entries?access_token=afa8ba8572bb0232644d94c80cfd4ae01314cd0589b98551147aab50f7134e30')
        .then(function(response){
            if(response && response.data && response.data.items){
                posts = response.data.items;
                defer.resolve(posts);
            }
        });

        return defer.promise;
    };        
}]);

Use in controllers:

postFetcher.getList().then(function(data){
//data processing;
});
Sign up to request clarification or add additional context in comments.

Comments

2

You return a promise to the caller. That way, the caller can "listen" to the promise. In order to return just posts, you have to append a then which returns response.data.items. The then that gets chained afterwards resolves that value.

getList: function(){
  return $http.get(...).then(function(response){
    // resolve just `response.data.items` to the next attached then which
    // would be from the caller of getList
    return response.data.items;
  });
}

That way, the caller can also attach a then from the promise:

postFetcher.getList().then(function(posts){
  // use `posts` (which is response.data.items)
});

In order to just call it once, you could store the promise in a variable. Then have getList return that promise. Attaching then to already resolved promises should resolve immediately to the resolved value.

var posts =  $http.get(...).then(function(response){
  return response.data.items;
});

return {
  getList: function(){
    return posts;
  }
}

// Call getList() the same way as above

4 Comments

Nice, this makes sense. However, is there a way to keep the http request outside of the return function?
Awesome. One last question if you don't mind. When you store the $http.get into posts, is the query actually being executed? Or is it not being executed until i call getList() in my controller?
@ByronS it's executed when the factory is created.
In your example, inside the second then function the posts parameter is not the value returned from the first then. It is the same value received in "response"

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.