2014-09-21 27 views
1

我想创建一个角度服务,它在“启动”时抓取数据并构建一个在应用程序的生命周期中不会改变的数组。我不想返回http请求的承诺。缓存结果仍然会导致'someExpensiveFunctionCall'的成本。处理这种情况的最佳方式是什么,可以确保服务将结果填充并可以在控制器和/或其他服务中使用。角度最佳实践:在服务启动时的数据

angular.module('app') 
.service('MyService', function($http, defaults) { 
    var result = []; 
    $http.get('/some/url').then(function(data) { 
    if(angular.isDefined(data)) { 
     _.forEach(data, function(item) { 
     result.push(someExpensiveFunctionCall(item.value)); 
     }); 
    } else { 
     result = angular.copy(defaults.defaultResult); 
    } 
    }); 
    return { 
    result: result 
    }; 
}) 
.controller(function(MyService) { 
    var someData = MyService.result; 
}) 
.service(function(MyService) { 
    var someData = MyService.result; 
}); 

回答

1

我不想返回HTTP请求的承诺。

看起来好像你想做一些异步的事情;同步。如果没有某种回调,承诺,同步XHR或其他机制,这将无法工作(可靠)。

知道我们可以评估一些选项。 (按照最实用的顺序)

  1. 使用路由器resolve属性。这将在实例化控制器之前完成一些承诺返回操作。它也(在ui-routerngRoute中)表示承诺的结果将按照指定的键名注入到控制器中。

  2. 使用承诺。

(又名#1手动地)

.factory('MyService',function($http,defaults){ 
    var ret = {result: []}; 
    ret.promise = $http.get('url').then(function(data){ 
     if(angular.isDefined(data)){ 
      _.forEach(data,function(item){ 
       ret.result.push(someExpensiveFunctionCall(item.value)); 
      }); 
     }else{ 
      _.forEach(angular.copy(defaults.defaultResult),function(val){ 
       ret.result.push(val);  
      }); 
     } 
     return ret; 
    });   
    return ret; 
}) 
.controller('MyCtrl',function(MyService){ 
    MyService.promise.then(myCtrl); 
    function myCtrl(){ 
     var result = MyService.result 
    } 
}) 
  • 懒惰评价。 - >由于脏检查,这是有点慢的角度。但本质上意味着您不会立即在控制器或服务的主体内操作/阅读result。相反,使用视图绑定,过滤器和交互来调用作用于数据的范围函数。由于承诺的解决将调用摘要循环。当数据到达时,您的视图将呈现。
  • 如果data恰好是未定义的,则代码中存在一个错误。通过将result设置为默认值的副本,您可以取消引用result。 因此,所有对MyService.result的引用都将是一个空数组,永远不会是默认值。 为了保持参考我会循环默认并将其添加到resultresult.push

    希望这会有所帮助!