我有一个保存列表的数据库。我有一个表单,它通过factory
向数据库列表添加一行。添加行后,服务器将发回更新的列表。使用$http.post
返回的$q.defer().promise
,我用defer.resolve
更新的列表更新controller
内$scope
上的列表。
在测试时,我遇到了异常情况。我的问题是,如果我离开具有执行更新controller
的view
并返回更新完成前的view
,则当更新完成时,$scope
不会使用更新的列表进行更新 - 好吧,无论如何它都不会在view
中更新。如果我离开(在 SPA 内),然后再次返回,我会得到正确的数据。
执行更新的factory
从其setData
函数中的post
返回promise
。当承诺解析时,$scope
将更新。
这是controller
中的代码,耐心等待$http.post
解析:
promise.then(function() {
$scope.people = dataService.getData();
$scope.newperson = '';
$scope.submitting = false;
$scope.$apply();
});
这是相应视图中的 html,它应该与 $scope.people
无缝绑定:
<li class="list-group-item" ng-repeat="person in people">{{person.firstName}} {{person.lastName}}</li>
我在这个JSBin中模仿了缓慢的服务器响应(使用setTimeout):https://jsbin.com/hihazegosi/1/edit?js,console,output
要重新创建问题:
- 导航到
People
- 添加人员。在控制台中查看调用的帖子。
- 在 5 秒内导航到
Home
并返回People
。 - 等待人员,并在控制台中注意应已将人员添加到范围。
- 如果导航到
Home
并直接返回到People
,您将看到模型已更新。
请注意,如果您 a) 在帖子完成后导航回People
,您将看到正确的数据。如果您 b) 留在People
上,您将看到正确的数据。 调用$scope.$apply()
而不检查$scope.$$phase
因为这在所有情况下都会返回'$digest'
,因此您将在方案 b 中看到错误。
谁能解释一下这里发生了什么,以及是否有办法让$scope
和view
在这种情况下保持同步?
正在发生的事情是这样的:
- 当您离开人员状态时,控制器及其范围被破坏
- 因此,当
dataService.setData
承诺解析时,它$scope
不是指人员控制器的范围(它指的是您导航离开之前的旧控制器) - 然后,当您切换到主页并随后切换回人员时,将再次重新创建人员控制器,并且在其构造函数中执行
dataService.getData
然后用正确的值填充其$scope.people
我认为您需要将人员列表存储在状态更改中持续存在的某个地方,例如在dataService
服务中
您还可以使用 $broadcast
在控制器需要更新时将消息传递给控制器。您可以像这样执行此操作:
- 当
dataService.setData
解析时,执行$rootScope.$broadcast('peopleUpdated')
- 这会将消息从根范围向下发送到应用中的所有范围 - 使用
$scope.$on('peopleUpdated', function() { $scope.people = dataService.getData(); })
在控制器中侦听此事件