7

我在 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的 inAppCtrl已正确更新(项目数组)但我$scope.projectinProjectCtrl未更新。我可以在函数内部登录,它会准确地记录我的期望,我可以登录,它会相应地更新,但是当我尝试登录我的控制器时,它不会相应地更新。array[i]updateObjectInArray()$scope.projectsAppCtrl$scope.projectProjectCtrl

我认为原因是因为我必须调用$rootScope.$apply()或者$rootScope.$digest()在我更新了中的array[i]对象之后updateObjectInArray(),但是,我得到了$digest is already in progress.

我需要做些什么来确保我$scope.project的数组中的项目在我的ProjectCtrl? 我需要为它解决一个新的承诺吗?

4

2 回答 2

14

加载后projects,您将使用数组中的一项,projects[i]理论上假设它是0x1内存中的对象。问题是,当加载一个新项目(假设0x2)并更新数组时,您正在更改驻留在数组位置(0x1)中的对象,但$scope.project仍引用现在废弃的 object 0x1。不能只在数组中更改,必须修改,所以不需要重新绑定$scope.project变量。

最好的解决方案是更改 array[i] = newData angular.extend(array[i], newData). 这样,您只需更改 array[i] 的所有属性,并且当您$scope.project指向内存中的同一个对象时,它将被更新。

Anyway, I also believe you may want to change if(array[i] == object) { to if(array[i]._id === object._id) { and your equality comparisons (==) to strictly equality comparisons (===). This if suits better your cause, as the new created object is not the same as the old one.

于 2013-01-15T12:05:36.053 回答
3

$scope.projects在绑定中使用吗?还是代码中的其他地方?

因为你正在返回而询问,并且承诺永远不会被它的结果改变,尽管你可以将承诺直接绑定到期望它的内容的 HTML。发生这种情况是因为,在内部,Angular 似乎在关注它的结果。

所以,如果你在其他地方使用这个变量,那么你需要使用$q.when($scope.projects). 您将获得一个新的承诺,如果它已经解决,它将立即解决。

于 2013-01-14T08:46:32.220 回答