我在Angular中创建了一个看起来像这样的控制器(为简洁而编辑):
function AppCtrl($scope, $http, $location, $dataService) {
$scope.projects = $dataService.data.projects;
}
正确加载$scope.projects
服务中的$dataService
承诺。
app.service('$dataService', function($q, $http, $location, $rootScope) {
var dataService = this; //Provides access 'this' inside functions below
var projectsDeferred = $q.defer();
$http.get('/api').success(function(data, status, headers, config) {
projectsDeferred.resolve(data.projects);
}).error(function(err) {
projectsDeferred.reject(err);
});
this.data = {projects: projectsDeferred.promise};
//UPDATE FUNCTION
function updateObjectInArray(array, object, newData) {
for(i in array) {
if(array[i] == object) {
if(newData != undefined) {
array[i] = newData;
} else {
return array[i];
}
}
}
return undefined;
}
this.updateProject = function(project, updateData) {
$http.put('/api/projects/' + project._id, updateData)
.success(function(data, status, headers, config) {
updateObjectInArray(dataService.data.projects.$$v, project, data);
}).error(function(data, status, headers, config) {});
};
});
我创建了另一个看起来像这样的控制器,它根据当前的URL从项目数组中选择一个项目:
function ProjectCtrl($scope, $route) {
//Getting the current project from the array of projects
$scope.project = $scope.projects.then(function(projects) {
for(i in projects) {
if(projects[i]._id == $route.current.params.projectId) {
return projects[i];
}
}
});
}
当我尝试运行updateObjectInArray()
函数时(关于$http.put()
请求成功),$scope.projects
中的AppCtrl
已正确更新(项目数组)但$scope.project
中的ProjectCtrl
未更新。我可以在array[i]
函数中记录updateObjectInArray()
,它会准确记录我的预期,并且我可以在$scope.projects
中记录AppCtrl
,它会相应更新,但是当我尝试时要在我的$scope.project
控制器中记录ProjectCtrl
,不会相应更新。
我认为原因是因为我在更新$rootScope.$apply()
中的$rootScope.$digest()
对象后不得不拨打array[i]
或updateObjectInArray()
,但是,我收到的错误是{{ 1}}。
我需要做些什么来确保我的$digest is already in progress
中的数组中的$scope.project
项目得到更新?我是否需要为此解决新的承诺?
答案 0 :(得分:14)
加载projects
后,您正在使用数组projects[i]
中的一个项目,理论上我们假设它是内存中的对象0x1
。问题是,当加载一个新项目时(让我们假设0x2
),并且您更新了数组,您将更改位于数组位置的对象(0x1
),但是{{ 1}}仍然引用现在放弃的对象$scope.project
。您不能只在数组中更改它,您必须修改它,因此您不需要重新绑定0x1
变量。
最佳解决方案是更改 $scope.project
至 array[i] = newData
。这样,您只需更改数组[i]的所有属性,并且当您的angular.extend(array[i], newData)
指向内存中的同一对象时,它将被更新。
无论如何,我也相信您可能希望更改 $scope.project
到 if(array[i] == object) {
以及您的平等比较({{1} })到严格的相等比较(if(array[i]._id === object._id) {
)。这个==
更适合您的原因,因为新创建的对象与旧对象不同。
答案 1 :(得分:3)
您是否在绑定中使用$scope.projects
?或者代码中的其他地方?
要求因为你正在返回,并且承诺永远不会被它的结果改变,尽管你可以将promises直接绑定到期望它的内容的HTML。这是因为,在内部,Angular似乎注意到它的结果。
因此,如果您在其他地方使用此变量,则需要使用$q.when($scope.projects)
。您将获得一个新的承诺,如果它已经解决,将立即得到解决。