【问题标题】:AngularJS view not updating after model change模型更改后AngularJS视图不更新
【发布时间】:2016-11-11 19:11:05
【问题描述】:

我正在编写一个基于网络的游戏,让您可以对卡片出价并与其他玩家进行交易。对于这个应用程序,我使用的是 Node、Express、MongoDB 和 Angular。

视图显示玩家头像和名称以及他们的连接状态。此连接状态保存在游戏模型中,但也通过 socket.io websockets 实时跟踪。

当玩家加入游戏时,服务器会向所有客户端发送消息。然后,客户端通过比较游戏 ID 来检查消息是否是针对他们的。

socketService.on("playerConnection", function(data) {
    if (data.gameId === gameId) {
        handlePlayerConnection(data);
    }
});

如果消息是发给我们的客户端的,则将数据传递给函数“handlePlayerConnection”。

function handlePlayerConnection(data) {
    if ($scope.game) {
        for (var i = 0; i < $scope.game.players.length; i++) {
            if ($scope.game.players[i].user.id === data.userId) {
                $scope.game.players[i].isConnected = data.connected;
            }
        }
    }
}

在视图中,我只是将玩家头像绑定到“isConnected”,因此当玩家连接/断开连接时它会显示/隐藏。

游戏模型时不时地发生变化(很明显),服务器会通知客户端(再次通过套接字)刷新 $scope.game。

下面的代码展示了如何刷新 $scope.game。

function getGame(gameId, callback) {
    gameService.getGame(gameId, function(err, data) {
        if (!err) {
            $scope.game = data; // Set game

            if (callback) callback(data);
        }
    });
}

此时,视野基本定格。它完全停止响应玩家连接和断开连接。刷新浏览器或控制器可以解决问题。

我已将 $scope.game.players 记录到控制台,它似乎包含正确的连接状态。该视图根本没有响应。 我尝试以各种方式和位置实现 $scope.$apply(),但给我的只是'angular.js:13920 Error: [$rootScope:inprog] $apply already in progress' .在 $timeout() 中包装 $scope.$apply() 可以消除上述错误,但不能解决问题。

花了几个小时试图解决这个问题后,我可能会遇到隧道视觉问题。对任何可以帮助我的人表示无尽的赞誉。

编辑:刚刚意识到所有套接字数据都是通过 $rootScope.apply() 处理的。 完整代码:

var socket = io.connect("http://localhost:8180/");
return {
    on: function(eventName, callback) {
        socket.on(eventName, function() {
            var args = arguments;
            $rootScope.$apply(function() {
                callback.apply(socket, args);
            });
        });
    },
    emit: function(eventName, data, callback) {
        socket.emit(eventName, data, function() {
            var args = arguments;
            $rootScope.$apply(function() {
                if (callback) {
                    callback.apply(socket, args);
                }
            });
        })
    },
    off: function(eventName) {
        socket.off(eventName);
    }
};

现在我什至不太确定该怎么做..

【问题讨论】:

    标签: javascript angularjs node.js express


    【解决方案1】:
    if (!$scope.$$phase) {
        $scope.game = data; // Set game
    
        if (callback) callback(data);
    }
    

    如果当前没有进行摘要,这将触发摘要。否则,您的代码将被正在运行的摘要更新。

    【讨论】:

    • 不幸的是,此检查使我的视图完全空白。没有要显示的数据。
    • 尝试将您的 $scope.game 数据包装在一个对象中,并将更新结果设置为该对象上的一个字段,并让三个 UI 监听该字段。当您更改对象时,Angular 可能会丢失他的引用。
    • 没问题,希望我的回答对您有所帮助。
    【解决方案2】:

    终于修好了……

    我忘记了我将指令用作“播放器”。出于懒惰的原因,我没有创建一个孤立的范围并传递播放器对象,而是通过以下方式将播放器对象分配给范围:

    link: function(scope, elem, attrs) {
            /*
                Decided not to use an isolated scope because the
                player directive needs access to the $rootScope.
                The solution below eliminates the need of said scope.
            */
            scope.player = scope.$eval(attrs.player);
    
        }
    

    如您所见,甚至有一条评论解释了我的愚蠢决定。

    【讨论】:

      猜你喜欢
      • 2014-02-13
      • 2013-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多