为什么我必须将 $promise 与 $resource 一起使用?

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

诚然,我对 Angular 比较陌生,但我已经摆脱了使用 ngResource 进行 REST 调用的困境。

我遵循了一个工厂模式,这个模式看起来比较普遍。

但是我只能使用 $promise.then 访问 REST 响应。我知道你不需要 $resource.

所以我有这个工厂...

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

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

这失败了(未定义)

alert(Lookups.get().foo);

但这很好

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

我显然在这里遗漏了一些东西。某种小学生错误 ;-)

更新

感谢您的帮助 - 现在很清楚了。我给@fikkatra打了勾,因为她的回答和片段很清晰。但几乎所有的答案都是有帮助的。我必须小心使用 Alert 进行调试!

您不必,也不应该将 $promise$resource 结合使用。 $resource 服务可以这样使用:

(function() {
  'use strict';

  angular
    .module('app')
    .factory('MyService', MyService);

  MyService.$inject = ['$resource'];

  function MyService($resource) {
    return $resource('my/url/:id', {id: "@id"}, {
      'query': { isArray: false },
      'update': { method: "put" }
    });
  }
})();

它会返回几个 HTTP 方法,您可以在代码中使用这些方法,而无需自己编写。要使用它们,您可以这样做:

function getActionTypes(){
      MyService.query(
        function success(result){
          // do stuff with result
        },
        function failure(result){
          console.error(result);
        });
    }

对承诺使用 alert 无效,即它不会显示承诺中的结果。但是,angular 被设计为直接使用 $resource 服务绑定到作用域。这意味着您可以将 $resource 结果绑定到范围对象,并且 angular 将在应用绑定时考虑范围对象是一个承诺。这就是为什么 alert(resourceResult) 不起作用,但 $scope.myObj = resourceResult;(然后将其绑定到视图中)会起作用的原因。

插入代码片段以更清楚地解释事情:

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>

根据 specification,您可以按照这个小代码片段中的概述传递成功回调。

var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
  user.abc = true;
  user.$save();
});

资源完成时将调用成功回调函数。


或者,您可以将 promise 语法与 get() 结合使用,除非您不需要根据您的示例添加自己的 promise。相反,您可以简单地执行以下操作:

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

这是因为get()returns一个承诺。当 promise 被成功评估时 then() 将被调用

您实际上没有使用 $promise,只要您愿意,它就可用。

代码笔:http://codepen.io/troylelandshields/pen/bpLoxE

angular.module('app', ['ngResource'])
.service('exampleSvc', function($resource){
  return $resource('http://jsonplaceholder.typicode.com/posts/1', {});
})
.controller('exampleCtrl', function(exampleSvc, $scope){
  $scope.result = exampleSvc.get(); 

  exampleSvc.get().$promise.then(function(val){
    //Do some other logic here on the val
    $scope.promiseResult = val;
  });

});

您还可以将 .get() 的结果分配给作用域上的一个变量,当请求被解析时,结果将被填充(在上面的第一个例子中)。这适用于将数据分配给范围内的对象,该对象最终将显示在页面上,但对于需要使用 .get() 的结果执行其他操作的其他情况可能效果不佳。