2014-03-01 26 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個完成時一次填充所有內容。 –