【问题标题】:Frequent updates to Angular controller not reflected in viewAngular 控制器的频繁更新未反映在视图中
【发布时间】:2014-02-03 05:49:11
【问题描述】:

使用 Angular 解决一个有趣的问题,并从 SignalR 频繁更新。

在服务器上,我有一个管理器的单例实例,当前设置为每 500 毫秒发送一次更新

    public void StartTest() {
        var i = 0;
        while (i < 1000) {
            if (_cancelRequested) {
                _cancelRequested = false;
                return;
            }
            _context.Clients.All.sent(i++);
            Thread.Sleep(500);            

在我看来,我使用“controller as vm”语法:

{{vm.status}}

终于在我的控制器中(在 signalR 初始化时):

    // Using 'Controller As' syntax, so we assign this to the vm variable (for viewmodel).
    var vm = this;
    vm.status = '';
    ...
    function activateSignal() {
        var hub = $.connection.mailerHub;

        hub.client.sent = function (counter) {
            log(' singal_R ## event: sent ' + counter);  // <-- this works on every update
            vm.status = counter;  // this works only on last update, or if stop is pressed it writes the most recent update. 
        };

该代码做了两件事:写入日志(这会向浏览器发送 toastr 更新),并在控制器上设置状态变量。

日志 cmets 按预期反映在浏览器中,每半秒我都会收到带有事件编号的漂亮 toastr 通知,但是设置变量没有任何效果,直到我请求停止或达到 999。

当我按下停止时,vm.status 被写出最后一个序列号,或者当整个事情停止时,它写出 999。

所以在 vm 上设置属性的频率似乎有些问题?我需要像 $scope.$watch 这样的东西来完成这项工作吗?

【问题讨论】:

    标签: javascript angularjs signalr


    【解决方案1】:

    嗯,对我来说,你想要实现的目标还不够清楚,但看起来你正在更新你的模型,超出了角度的控制。所以,你需要通知 Angular 你在做什么。

    很可能,这样的事情应该可以解决问题:

    hub.client.sent = function (counter) {
       $scope.apply(function(){
          log(' singal_R ## event: sent ' + counter);
          vm.status = counter;
       });
    };
    

    【讨论】:

    • 我没有使用范围......使用“控制器作为”表示法,所以我的所有属性都设置在控制器上。当更新像这样连续发生时,它似乎适用于所有接受的东西..但是最后一次更新通过..
    • @SonicSoul 我必须同意埃德温的回答。您实际上仍在使用范围,尽管在后台。 “controller as”表示法只是意味着 Angular 将控制器实例发布到作用域上,这就是为什么您的属性可以在视图中访问的原因。例如。如果您在视图中使用yourController as vm,则实际上在作用域$scope.vm 上会有一个属性。由于 SignalR 在 Angular 上下文之外与客户端通信,因此您必须使用 $scope.$apply 让 Angular 知道您的模型已更改。
    • 因此,即使您使用controller as 表示法,在某些情况下,例如您的示例,或者如果您想在 $scope 上订阅或发出/广播事件,您仍然需要将 $scope 注入你的控制器。这也是我将控制器作为符号的原因之一。现在我在我的控制器中使用$scope.vm = {};,然后把我想暴露的所有东西放在$scope.vm上。
    • 哎呀,我之前的评论太仓促了。包装在 $scope.$apply 确实解决了这个问题。谢谢!
    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多