AngularJS: ajax调用后模板中的作用域没有更新

AngularJS: scope not updating in template after ajax call

本文关键字:作用域 更新 ajax 调用 AngularJS      更新时间:2023-09-26

我有这样一个对象数组:

$scope.posts = [
    { 
        "name" : "name1",
        "age" : 12
    },
    { 
        "name" : "name1",
        "age" : 13
    },
    { 
        "name" : "name1",
        "age" : 14
    }
]

我在我的标记中重复这个数组,如下所示:

<div ng-repeat="post in posts">
    <span>{{post.name}}</span>
    <button ng-click="editPost(post)">Click!</button> <!-- passing post as argument here-->
</div>

控制器:

app.controller('PostController', function($scope, postFactory){
    //array is present in controller, just not showing it here
    $scope.editPost = function(post) {
        postFactory.editPost(post).then(function(data) { //factory having an ajax call which gets new data to be assigned to 'post'
            post = angular.copy(data.data)
            console.log(post); //here new data is populated successfully
        })
    }
})

正如你所看到的,当'editPost'被调用时,新的post数据通过工厂从API中获取并分配给'post'(这是'editPost'函数的参数)。当我在分配新数据后的控制台日志"post"时,它会在控制台中显示新数据。然而,在我的标记中,仍然显示旧的数据。知道为什么标记没有更新吗?这是我的工厂:

app.factory('postFactory', function($http) {
    return {
        editPost : editPost
    }
    function editPost(post) {
        return $http.post('<api>', post).success(function(response) {
            return response.data;
        })
    }
})
编辑:

我刚注意到一件事。当我改变:

post = angular.copy(data.data)

post.name = data.data.name;

帖子被更新。所以,我猜一个对象的质量分配没有得到更新,但当我更新一个单独的属性,它在模板中得到更新。

简短的回答:引用是"按值传递"给函数的。

长答:

当你将一个对象传递给一个函数时,函数将接收一个对该对象的引用的副本。当您覆盖该引用时,结果将仅在该函数的作用域中可见。

换句话说,当你在做:

post = angular.copy(data.data)

你只改变了post(在editPost里面)指向的东西。这将对外部世界/作用域没有影响(我说的作用域是指普通的JS函数作用域,而不是Angular的作用域)。

使代码工作的一种可能方法是将$index值传递给editPost,然后像这样修改$scope.posts:

$scope.editPost = function(index) {
        postFactory.editPost($scope.posts[index]).then(function(data) { 
            $scope.posts[index]= angular.copy(data.data)
        })
    }
编辑:

既然我的解释不够清楚,我将尽量详细说明。

假设内存中有一个对象。我们称这个对象为objInMem。该对象被vars引用。从本质上讲,var就像一个箭头,指向内存中的某个位置,即对象所在的位置。

someVar -> objInMem

当然,该引用的值(对象的"地址")也在内存中,可以通过将其分配给其他vars来复制。

var otherVar = someVar; // someVar -> objInMem <- otherVar

当你调用一个接受一个对象的函数时,JS会复制你传递的引用的值,并把这个副本"给"给这个函数。

function f(obj) {...}
f(someVar); // someVar -> objInMem <- obj (inside function f)

当你尝试给obj赋值时(在f的内部),它只是改变了该引用的值,但原始引用将保持不变:

obj = someOtherThing; // obj -> someOtherThingInMem
// someVar -> objInMem (still the same)

我希望这能澄清问题。它有点过于简化,不包括简单的值(如数字),但它应该解释这种特定情况。

很可能angular没有意识到异步更新。

尝试像这样将它包装在超时中:

$timeout(function(){
  post = angular.copy(data.data)
});