使用$ q promise,就像$ resource返回的promise一样

时间:2015-04-14 22:38:12

标签: angularjs q ngresource

使用angular的$ resource资源承诺,我可以将promise直接分配给变量,并在成功函数中将promise的结果分配给varible。我想知道我是否能用$ q实现同样的目标?

实施例

.service("rest", function($resource){
        return {
            user: $resource( "http://some.com/url")
        }
    })
    .controller("myCtrl", function($scope, rest){
        $scope.user = rest.user.get(); <-- This is what I want to be able to do with $q
    })

4 个答案:

答案 0 :(得分:3)

简答:否

$resource界面专门用于允许这种“未来”行为。当您致电.get()时,它会返回一个占位符对象,该对象将在可用时填充数据。

因为$resource是一个内部Angular工厂,它知道何时触发摘要周期,这使得您似乎可以从头开始使用$scope.user。实际上,在服务器发出HTTP响应之前,不会填充数据。

另一方面,承诺是一种通用机制。它不知道什么样的占位符对象在它们到达时存储它的值。它不会带来什么样的价值。因此,promises公开了一系列回调方法,我们可以用它来告诉我们什么时候准备就绪。


长答案:排序(你可以使用promises来构建像这样工作的接口)

这种机制只能用于Angular对作用域进行脏检查的方式。当异步发生时,需要让Angular知道它应该检查是否有任何变化,并且需要更新它的视图。

当数据从我们的HTTP响应中到达时,$resource工厂负责让Angular知道。这意味着$scope.user对象一到达即会显示在您的视图中。 $resource负责在异步事件发生时使事情发生。在这种情况下,异步事件是与数据一起到达的HTTP响应。

使用promises时,您负责在异步事件发生时使事情发生。承诺特定于Angular,因此promises有一个通用接口,用于处理可能发生在promise中的不同异步事件。当其中一个发生时,这是你的工作,这就是为什么简短的答案是否定的。

然而,如果您正在实施工厂/服务/提供商,可能需要此行为,则可能。

让我们创建一个火箭工厂,创建火箭实例,稍后将使用$resource工厂以与$q相同的方式添加其部件。

app.factory('Rocket', function(Junkyard) {
  return function(name) {
    var rocket = {};

    rocket.name = name || 'Boring Rocket';
    rocket.parts = [];
    rocket.promise = Junkyard.getParts();

    // Junkyard.getParts returns a $q promise
    // which will be resolved with an object
    // of things that can be attached to the rocket.
    //
    // It might look something like this
    // [
    //   { name: "thrusters", "quantity":  3 },
    //   { name: "engines", "quantity": 100 },
    //   { name: "robots", "quantity": 2 }
    // ]

    rocket.promise.then(function(parts) {
      parts.forEach(function(part) {
        rocket.parts.push(part);
      });
    });

    return rocket;
  };
});

现在我们可以以与$resource

类似的方式使用我们的新工厂
function MyController($scope, Rocket) {
  $scope.rocket = Rocket('Top Rocket');
  // we can use $scope.rocket here!

  $scope.rocket.name = 'Even Better Rocket';
  // but it won't have the properties from
  // Junkyard.getParts yet.
}

我们可以将这些值直接模板化到我们的视图中。

<section ng-controller='MyController'>
  <h1 ng-bind='rocket.name'></h1>
  <table>
    <th>
      <td>Name</td>
    </th>
    <th>Description</th>
    <tr ng-repeat='part in rocket.parts'>
      <td ng-bind='part.name'></td>
      <td ng-bind='part.description'></td>
    </tr>
  </table>
</section>

一旦promise解析,属性将被添加到火箭中,范围摘要将由$q触发,因为$q知道刚刚发生了异步事件。

答案 1 :(得分:0)

从Angular中删除了将promises直接分配给变量并在模板中呈现它们的功能。看到这个重大变化:Templates no longer automatically unwrap promises。相反,当解析或拒绝承诺时,您必须在回调中分配scope属性。

答案 2 :(得分:0)

您可以,只返回一个更新的对象而不是一个promise。 jsfiddle

var getUser = function(base) {
    var user = base || {};

    // replace with actual request
    $timeout(function() {    
        // make sure to use angular.copy so the same object is used
        angular.copy({
            id: 1,
            username: 'anon',
            roles: [
                { id: 1, title: 'user' },
                { id: 2, title: 'admin' },
                { id: 3, title: 'editor' }
            ]
        }, user);
    }, 3000);
    return user;
};

$scope.user = getUser({roles: []});

答案 3 :(得分:0)

这样做(它是一个coffeescript),

service.getSomeData = () ->
    data = {}
    $http.get("/getSomeData").then (resp) ->
      angular.copy(resp.data, data)

   return data

在控制器中你可以这样做

 $scope.data = service.getSomeData()