【问题标题】:use the $q promise like the promise returned from $resource使用 $q 承诺,就像从 $resource 返回的承诺一样
【发布时间】:2015-06-20 17:26:01
【问题描述】:

使用 Angular 的 $resource 承诺,我可以将承诺重新分配给变量并使用它,而无需将承诺的结果分配给成功函数中的变量。我想知道我是否可以用 $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
    })

【问题讨论】:

    标签: angularjs q ngresource


    【解决方案1】:

    这样做很有效(它是一个咖啡脚本),

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

    在控制器中你可以这样做

     $scope.data = service.getSomeData()
    

    【讨论】:

      【解决方案2】:

      你可以,只返回一个更新的对象而不是一个承诺。 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】:

        简短回答:否

        $resource 接口专门设计用于允许这种“期货”行为。当您调用 .get() 时,它会返回一个占位符对象,该对象将在可用时填充数据。

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

        另一方面,Promise 是一种通用机制。它不知道在它们到达时将其值存储在哪种占位符对象中。也不会到达什么样的值。因此,promise 公开了一系列回调方法,我们可以使用这些方法来让我们知道 promise 何时准备就绪。


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

        这种机制之所以有效,是因为 Angular 对范围进行脏检查的方式。当异步发生时,需要让 Angular 知道它应该检查是否有任何变化,并且需要更新它的视图。

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

        使用 Promise 时,您有责任在异步事件发生时让事情发生。它将是特定于 Angular 的 Promise,因此 Promise 有一个通用接口来处理可能发生在 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 解决,属性将被添加到 Rocket 中,并且范围摘要将由 $q 触发,因为 $q 知道刚刚发生了异步事件。

        【讨论】:

        • 嘿,我非常感谢详细的回答和快速的回​​复!我会在这里发布任何问题。再次感谢您!
        【解决方案4】:

        Angular 已移除将 Promise 直接分配给变量并在模板中呈现它们的功能。请参阅此重大更改:Templates no longer automatically unwrap promises。相反,当 promise 被解析或拒绝时,您必须在回调中分配 scope 属性。

        【讨论】:

        • 我不认为这个问题提到了在模板中渲染承诺。更多的是关于如何以非标准方式使用 Promise。
        猜你喜欢
        • 2016-03-18
        • 2015-06-05
        • 1970-01-01
        • 2015-11-27
        • 1970-01-01
        • 2016-06-15
        • 1970-01-01
        • 1970-01-01
        • 2015-05-12
        相关资源
        最近更新 更多