我在我的应用程序有以下服务:
uaInProgressApp.factory('uaProgressService',function(uaApiInterface,$timeout,$rootScope){ var factory = {}; factory.taskResource = uaApiInterface.taskResource() factory.taskList = []; factory.cron = undefined; factory.updateTaskList = function() { factory.taskResource.query(function(data){ factory.taskList = data; $rootScope.$digest console.log(factory.taskList); }); factory.cron = $timeout(factory.updateTaskList,5000); } factory.startCron = function () { factory.cron = $timeout(factory.updateTaskList,5000); } factory.stopCron = function (){ $timeout.cancel(factory.cron); } return factory; });
然后我在一个控制器中使用它,像这样:
uaInProgressApp.controller('ua.InProgressController',function ($scope,$rootScope,$routeParams,uaContext,uaProgressService) { uaContext.getSession().then(function(){ uaContext.appName.set('Testing house'); uaContext.subAppName.set('In progress'); uaProgressService.startCron(); $scope.taskList = uaProgressService.taskList; }); } );
所以基本上我的服务更新factory.taskList每5秒,我链接这个factory.taskList到$ scope.taskList。然后我尝试不同的方法,如$ apply,$ digest,但factory.taskList上的更改不会反映在我的控制器和视图$ scope.taskList。
它在我的模板中保持为空。你知道我如何传播这些变化吗?
而使用$ watch可能解决问题,它不是最有效的解决方案。您可能想要更改在服务中存储数据的方式。
问题是,当范围被指向旧位置时,您每次为其分配一个新值时,将替换您的taskList所关联的内存位置。你可以看到这发生在this plunk。
当您首次加载plunk时,使用Chrome创建堆快照,在单击按钮后,您将看到范围指向的内存位置在列表指向不同内存位置时不会更新。
你可以很容易地解决这个问题,让你的服务持有一个对象,该对象包含可能改变的变量(类似于data:{task:[],x:[],z:[]})。在这种情况下,“数据”永远不应该更改,但任何其成员可以随时更改。然后将此数据变量传递到作用域,只要不通过将“数据”分配给其他内容来覆盖它,只要数据中的字段更改,作用域就会知道它并且将正确更新。
This plunk显示了使用上面建议的修复运行的相同示例。在这种情况下不需要使用任何观察者,如果发生某些事情没有在视图上更新,你知道你需要做的是运行范围$ apply来更新视图。
这样,您就不需要经常比较变量的观察者和需要观察许多变量的情况下的丑陋设置。这种方法的唯一问题是,在你的视图(html),你会有“数据”。前缀所有你曾经只有变量名的地方。