AngularJS - 如何强制更新范围(数组项的承诺) [英] AngularJS - how to force a scope to update (promise for array item)

查看:21
本文介绍了AngularJS - 如何强制更新范围(数组项的承诺)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Angular 中创建了一个如下所示的控制器(为简洁起见进行了编辑):

I've created a controller in Angular that looks like this (edited for brevity):

function AppCtrl($scope, $http, $location, $dataService) {
    $scope.projects = $dataService.data.projects;
}

从我的 $dataService 服务正确加载 $scope.projects 承诺.

Which correctly loads the $scope.projects promise from my $dataService service.

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 从项目数组中选择一个项目:

I've created another controller that looks like this, that selects a single project from the array of projects based on the current 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.projectsAppCtrl 中的 已正确更新(项目数组),但 ProjectCtrl 中的 $scope.projectnot 更新.我可以在 updateObjectInArray() 函数中记录 array[i] ,它会准确记录我期望的内容,并且我可以记录 $scope.projectsAppCtrl 中,它会相应地更新,但是当我尝试在我的 ProjectCtrl 控制器中记录 $scope.project 时,它 isn't 相应地更新.

When I try to run my updateObjectInArray() function (on the success of my $http.put() request), my $scope.projects in AppCtrl is correctly updated (the array of projects) but my $scope.project in ProjectCtrl is not updated. I can log array[i] inside the updateObjectInArray() function and it will log exactly what I expect, and I can log $scope.projects in AppCtrl and it will update accordingly, but when I try to log $scope.project in my ProjectCtrl controller, it isn't updated accordingly.

我认为原因是我更新了 array 后不得不调用 $rootScope.$apply()$rootScope.$digest()updateObjectInArray() 中的 [i] 对象,但是,我收到 $digest 已在进行中 的错误.

I thought the reason was because I had to call $rootScope.$apply() or $rootScope.$digest() after I updated the array[i] object in updateObjectInArray(), however, I get the error that $digest is already in progress.

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

What do I need to do to make sure my $scope.project item in the array gets updated in my ProjectCtrl? Do I need to resolve a new promise for it?

推荐答案

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

As soon as the projects are loaded, you're using one of the items from the array projects[i], let's theoretically assume it's the object 0x1 in memory. The problem is that when a new item is loaded (let's assume 0x2), and you update the array, you're changing the object that resides in the array position (the 0x1), but $scope.project still references the now abandoned object 0x1. You can't just change it in the array, you have to modify it, so you don't need to rebind the $scope.project variable.

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

The best solution is to change array[i] = newData to angular.extend(array[i], newData). This way, you gonna just change all properties of array[i], and as your $scope.project points to the same object in memory it will be updated.

无论如何,我也相信你可能想要改变 if(array[i] == object) { to if(array[i]._id === object._id) { 和你的相等比较(==)严格相等比较(<代码>===).此 if 更适合您的原因,因为新创建的对象与旧对象不同.

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.

这篇关于AngularJS - 如何强制更新范围(数组项的承诺)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆