2013-10-25 128 views
6

我的一個AngularJS控制器中包含此行:等待承諾加載資源之前解決

api.tickets.query() 

api模塊包含此:

angular.module('myapp.api', [ 
    'ngResource' 
]) 

.factory('api', function($resource, applicationsService) { 

    function fetchAppId() { 
    return applicationsService.getCurrentApp(); 
    } 

    return { 
    tickets: $resource('tickets', { 
     applicationId: fetchAppId 
    }), 
    ... 
    } 

applicationsService.getCurrentApp()使一個$ HTTP調用本身。所以你可能會看到這個問題 - 這個調用在fetchAppId()返回時可能沒有解決。

我該如何解決這個問題?

回答

6

比方說,從applicationsService以異步方式返回的數據:

var data = [ 
    { 
     "PreAlertInventory": "5.000000", 
     "SharesInInventory": "3.000000", 
     "TotalSharesSold": "2.000000" 
    } 

applicationsService工廠的回報承諾:

.factory('applicationsService', ['$resource','$q', function($resource, $q) { 
    var data = [ 
    { 
     "PreAlertInventory": "5.000000", 
     "SharesInInventory": "3.000000", 
     "TotalSharesSold": "2.000000" 
    } 
    ]; 

     var factory = { 
      getCurrentApp: function() { 
       var deferred = $q.defer(); 

       deferred.resolve(data); 

       return deferred.promise; 
      } 
     } 
     return factory; 
}]); 

我只想叫api.tickets()

$scope.data = api.tickets(); 

但我們api服務將是這樣的:

.factory('api', function($resource, applicationsService,$q, $timeout) { 

    function fetchAppId() {  
     return applicationsService.getCurrentApp(); 
    } 

    return { 
tickets: function() { 
     var deferred=$q.defer(); 
     fetchAppId().then(function(data) { // promise callback 
      $timeout(function(){   // added dummy timeout to simulate delay 
        deferred.resolve(data);  
       }, 3000);      
     }); 
     return deferred.promise; 
    } 
    } 
}); 

演示Fiddle

+0

賓果,感謝馬克西姆,像一個魅力工作。欣賞小提琴和細節:) –

+0

我認爲它的工作原理是因爲$ scope中的承諾等待$ apply()循環完成。正如文檔中所說的:「$ q與角度的$ rootScope.Scope Scope模型觀察機制集成在一起,這意味着更快地傳播分辨率或拒絕到模型中,並避免不必要的瀏覽器重繪,從而導致UI閃爍。 – Plap

+0

如果有人使用$ resource請求,那麼我們需要包含$ promise fetchAppId()。$ promise.then(function(data){----}); –

4

你需要做的是創造一個承諾你的自我。

.factory('api', function($resource, applicationsService,$q) { 

    function fetchAppId() { 
    return applicationsService.getCurrentApp(); 
    } 

    return { 
    tickets: function() { 
     var defer=$q.defer(); 
     fetchAppId().then(function(data) { 
      var appId=data; 
      $resource('tickets', {applicationId: appId}) 
       .then(function(data) { 
         defer.resolve(data); 
       }) 
     } 
     return defer.promise; 
    } 
    } 
1

如果你想等待一個角資源($resource)的路徑改變之前得到解決,那麼」需要退回$promise

$routeProvider.when('/tickets', { 
    resolve: { 
     'tickets': function ('Ticket') { 
      // do this to resolve the async call prior to controller load 
      return Ticket.query().$promise; 

      // this will resolve 'tickets' during/after controller load 
      return Ticket.query(); 
     } 
    }, 
    controller: ... 
});