2013-10-25 70 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: ... 
});