做到这一点没有问题!
您必须记住的主要事情是,您必须在服务中保持相同的对象引用(在 javascript 数组中是对象)。
这是我们的简单 HTML:
<div ng-controller = "companiesCtrl">
<ul ng-repeat="company in companies">
<li>{{company}}</li>
</ul>
</div>
这是我们的服务实现:
serviceDataCaching.service('companiesSrv', ['$timeout', function($timeout){
var self = this;
var httpResult = [
'company 1',
'company 2',
'company 3'
];
this.companies = ['preloaded company'];
this.getCompanies = function() {
// we simulate an async operation
return $timeout(function(){
// keep the array object reference!!
self.companies.splice(0, self.companies.length);
// if you use the following code:
// self.companies = [];
// the controller will loose the reference to the array object as we are creating an new one
// as a result it will no longer get the changes made here!
for(var i=0; i< httpResult.length; i++){
self.companies.push(httpResult[i]);
}
return self.companies;
}, 3000);
}}]);
最后是你想要的控制器:
serviceDataCaching.controller('companiesCtrl', function ($scope, companiesSrv) {
$scope.companies = companiesSrv.companies;
companiesSrv.getCompanies();
});
说明
如上所述,诀窍是保持服务和控制器之间的引用。一旦尊重这一点,您就可以将控制器范围完全绑定到服务的公共属性上。
Here a fiddle that wraps it up.
在代码的 cmets 中,您可以尝试取消注释不起作用的部分,您将看到控制器如何丢失引用。事实上,控制器将继续引用旧数组,而服务将更改新数组。
最后一件重要的事情:请记住,$timeout 会触发 rootSCope 上的 $apply()。这就是我们的控制器作用域“单独”刷新的原因。没有它,如果你尝试用普通的 setTimeout() 替换它,你会看到控制器没有更新公司列表。
要解决此问题,您可以:
- 如果您的数据是使用 $http 获取的,则不要执行任何操作,因为它会在成功时调用 $apply
- 换行会导致 $timeout(..., 0);
- 在服务中注入 $rootSCope 并在异步操作完成时对其调用 $apply()
- 在控制器中添加 $scope.$apply() 到 getCompanies() 承诺成功
希望这会有所帮助!