Search code examples
angularjsngresource

Why do I have to use $promise with $resource?


Admittedly I am relatively new to Angular but I've come unstuck using ngResource for a REST call.

I followed a factory pattern which seems to be relatively common.

However my I only get access to the REST response by using a $promise.then. Which I understand you do not require with $resource.

So I have this factory...

var LookupsService = angular.module('LookupsService', ['ngResource']);

LookupsService.factory('Lookups', ['$resource',
  function ($resource) {
      return $resource('http://localhost:5001/api/lookups', {});
  }]);

And this fails (as undefined)

alert(Lookups.get().foo);

But this is fine

    Lookups.get()
        .$promise
        .then(function (lookups) {
            alert(lookups.foo);
        });

I'm obviously missing something here. Some kind of schoolboy error ;-)

UPDATE

Thanks for all your help - it is now very clear. I gave @fikkatra the tick for the clarity of her answer and snippet. But pretty much all the answers were helpful. I must be careful using Alert for debugging!


Solution

  • Using alert on a promise won't work, i.e. it won't show the results within the promise. However, angular has been designed to use the $resource service directly to bind to the scope. This means you can bind a $resource result to a scope object, and angular will take into account that the scope object is a promise when applying the binding. That's why alert(resourceResult) won't work, but $scope.myObj = resourceResult; (and then bind it in a view), will work.

    Inserted code snippet to explain things more clearly:

    var app = angular.module('myapp', ['ngResource']);
    
    app.controller('myctrl', function($scope, $resource) {
      //this won't work:
      //alert("won't work: " + $resource('https://api.github.com/users/fikkatra').get());
      //but this will work
      $resource('https://api.github.com/users/fikkatra').get().$promise.then(function(user) {
        alert("will work: " + user.login);
      });
      //directly assigning $resource result to scope will work:
      $scope.user = $resource('https://api.github.com/users/fikkatra').get();
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-resource.js"></script>
    <div ng-app="myapp" ng-controller="myctrl">
      {{user.login}}
    </div>