2014-03-01 27 views
1

我已经定义了服务与功能是这样的:服务如何向控制器返回数据和多个承诺?

angular.module('common').factory('_o', ['$angularCacheFactory', '$http', '$q', '$resource', '$timeout', '_u', 

    function ($angularCacheFactory, $http, $q, $resource, $timeout, _u) {  

     var _getContentTypes = function ($scope) { 
      var defer = $q.defer(); 
      $http.get('/api/ContentType/GetSelect', { cache: _u.oyc }) 
       .success(function (data) { 
        $scope.option.contentTypes = data; 
        $scope.option.contentTypesPlus = [{ id: 0, name: '*' }].concat(data); 
        $scope.option.sContentType = parseInt(_u.oyc.get('sContentType')) || 0; 
        defer.resolve(); 
       }) 
      return defer.promise; 
     }; 

     return { 
      getContentTypes: _getContentTypes 
     } 

    }]); 

我打电话这在我的控制是这样的:

.controller('AdminProblemController', ['$http', '$q', '$resource', '$rootScope', '$scope', '_g', '_o', '_u', 
function ($http, $q, $resource, $rootScope, $scope, _g, _o, _u) { 

    $scope.entityType = "Problem"; 
    _u.oyc.put('adminPage', $scope.entityType.toLowerCase()); 

    $q.all([ 
     _o.getContentTypes($scope), 
     _o.getABC($scope), 
     _o.getDEF($scope) 
    ]) 

我是在说正确的,这是不使用的最佳方法服务。我想我应该返回 内容类型数据,然后在控制器中分配给范围内的服务。

但我不知道如何做到这一点,因为我的服务只是返回一个defer.promise,我使用$ q.all,所以我认为我应该在$ q.all已经为每个调用返回成功之后填充范围。

有人可以给我一些建议,我应该如何从承诺的服务中返回数据,并让$ q.all在所有调用成功完成后填充$作用域?

+0

你说的没错,这是一个使用服务......做你想要什么非常糟糕的方式,你应该在每种方法中返回诺言,然后你可以链接它们并在最后做一些事情,你只需要计算如何传递数据,以便它们都在结尾承诺 – doodeec

+0

btw中可用。 'http.get'已经返回一个promise,所以你不必将它包装在另一个promise中......并且在本周的javascript周刊中有一篇关于promises的很棒的文章,你会在那里找到一个'chain'模式 - http://taoofcode.net/promise-anti-patterns/ – doodeec

回答

2

你说控制器真的应该这样做是完全正确的,它会清除你的范围传递(并使其更加可重用)。我不知道你的确切用例,它有点令人困惑,但你可以通过挂钩由$http创建的承诺来实现,并且在所有承诺完成时仍然可以处理。

小提琴:http://jsfiddle.net/PtM8N/3/

HTML

<div ng-app="myApp" ng-controller="Ctrl"> 
    {{model | json}} 
    <div ng-show="loading">Loading...</div> 
</div> 

var app = angular.module("myApp", []); 

app.service("_service", ["$http", function (http) { 
    this.firstRequest = function() { 
     return http.get("http://json.ph/json?delay=1000") 
     .then(function (res) { 
      // manipulate data 
      res.data.something = new Date(); 
      return res.data; 
     }); 
    }; 
    this.secondRequest = function() { 
     return http.get("http://json.ph/json?delay=2000") 
     .then(function (res) { 
      // manipulate data 
      res.data.something = 12345; 
      return res.data; 
     }); 
    }; 
    this.thirdRequest = function() { 
     return http.get("http://json.ph/json?delay=3000") 
     .then(function (res) { 
      // manipulate data 
      res.data.something = "bacon"; 
      return res.data; 
     }); 
    }; 
}]); 

app.controller("Ctrl", ["$scope", "_service", "$q", function (scope, service, q) { 

    scope.loading = true; 
    scope.model = {}; 

    var firstRequest = service.firstRequest(); 
    var secondRequest = service.secondRequest(); 
    var thirdRequest = service.thirdRequest(); 

    q.all([firstRequest, secondRequest, thirdRequest]).then(function (responses) { 
     scope.model.first = responses[0]; 
     scope.model.second = responses[1]; 
     scope.model.third = responses[2]; 
     scope.loading = false; 
    }); 

}]); 
+0

丹,感谢您的帮助/建议。然而,我所寻找的只是如果所有的承诺都成功了,那么只能填充范围。看看你的代码,我认为它会填充范围,如果只有三个请求中的一个完成。像这样的东西:http://stackoverflow.com/questions/18153410/how-to-use-q-all-with-complex-array-of-promises –

+0

你不必马上使用数据,包裹在一个'ng-if'甚至根本没有纳入范围。但是,你想要的只是一个微调,2s。 –

+1

已更新为完成我的示例所做的操作,但是在全部3个完成时一次填充所有内容。 –