Q:

Fetch data using $http for use with a custom service

I'm trying to create a custom service which pulls the list of all defined statuses from the server for use in forms, so far I have:
SimpleTaskApp.factory('storyStatus', function($http) {
    var data = null;
    var promise = $http({
            url: '/story-status/',
            method: 'GET'
        }).success(function (resp) {
            data = resp;
        });
    return {list: data }};
});

I understand this won't work since $http is asynchronous, however I have no desire to run the request more than once. I'd like to treat it as a static variable in effect, so if ever storyStatus.list is called, it should check whether it is empty and then attempt to populate itself.

A:

You should work with promises instead of against them. 
You don't need to store the data because you can store the promise. The point of promises is that you don't know when they'll be done. You don't know when your data will be available.
So your service must return the promise. But that's okay:
SimpleTaskApp.factory('storyStatus', function($http) {
  var promise;

  function getData() {
    if ( ! angular.isDefined( promise ) ) {
      promise = $http({
        url: '/story-status/',
        method: 'GET'
      });
    }

    return promise;
  }

  return { list: getData };
});

In this service, your $http call will only be called once, but will return a promise whenever you call SimpleTaskApp.list(). Your controller that calls it doesn't need to know if the data is there yet because it will react the same regardless, e.g.:
SimpleTaskApp.controller('MainCtrl', function($scope, storyStatus) {
  storyStatus.list().then(function( data ) {
    $scope.statuses = data.statuses;
  });
});

If the data is already retrieved, the then will run basically immediately; if not, it will run when the data gets back. The controller doesn't need to know anything about the internal state of the storyStatus service.
So promises not only help with asynchronous tasks, but they also help keep our components decoupled, which is a big deal in AngularJS - and should be in other frameworks too!

