温馨提示:本文翻译自stackoverflow.com,查看原文请点击:callback - AngularJS Why is this controller variable not getting updated in the UI?
angularjs angularjs-scope callback model-binding stompjs

callback - AngularJS为什么该控制器变量无法在UI中更新?

发布于 2020-04-08 11:49:08

我有一个使用StompJS的控制器来订阅一个url(后端是Spring Java),该URL每5秒返回一个交替的字符串“ list”和“ box”。我想在StompJS收到一些数据时更新UI元素,但是无法获取UI元素进行更新。我已经使用来测试了相同的逻辑,$timeout并且UI正在更新,因此它必须与回调函数的工作方式有关。谁能看到UI不更新的原因是什么?

我有这些简单的UI元素:

<input ng-model="ctrl.uniqueId"/>
<input ng-model="test"/>

ctrl.uniqueId用于验证是否正在更新实际的控制器实例。由于某种原因,每次只有1个控制器进行5个不同的订阅。如果有人可以提供帮助,那也很好,但是我怀疑您会获得很多信息,除非您看到我所有的代码设置。

无论如何,在我的控制器中(尝试了self.test,它没有用,所以我尝试使用$ scope.test来查看它是否有所不同):

self.uniqueId = window.performance.now();
$scope.test = 'list';

// the UI will be updated to dummy after 3 seconds.
$timeout(function() {
    $scope.test="dummy";
}, 3000);

// the UI will not update.
var callBackFn = function(progress) {
    $scope.test = progress;
    console.log(self.uniqueId + ": " + $scope.test);
};

// the server returns alternating data (list and box) every 5 seconds
MyService.subscribeForUpdate('/topic/progressResults', callBackFn);

这很重要,这是我的StompJS服务代码:

self.subscribeForUpdate = function(channelUrl, callBackFn) {
    self.socket.stomp.connect({}, function() {
        self.socket.subscription = self.socket.stomp.subscribe(channelUrl, 
            function (result) {
                //return angular.fromJson(result.body);
                callBackFn(result.body);
                return result.body;
            }
        );
    });
};

console.log结果

1831.255000026431: list
1831.255000026431: box

另外:是否可以在没有回调函数的情况下获得类似于Promise的返回数据?

查看更多

提问者
user3758745
被浏览
73
georgeawg 2020-02-02 01:31

请务必使用$apply

app.service("myService", function($rootScope) {
    var self = this;
    self.subscribeForUpdate = function(channelUrl, callBackFn) {
        self.socket.stomp.connect({}, function() {
            self.socket.subscription = self.socket.stomp.subscribe(channelUrl, 
                function (result) {
                    //return angular.fromJson(result.body);
                    $rootScope.$apply(function() {
                        callBackFn(result.body);
                    });
                    return result.body;
                }
            );
        });
    };
})

AngularJS通过提供自己的事件处理循环来修改常规JavaScript流。这将JavaScript分为经典和AngularJS执行上下文。只有在AngularJS执行上下文中应用的操作才能从AngularJS数据绑定,异常处理,属性监视等中受益。您还可以$apply()用来从JavaScript输入AngularJS执行上下文。

请记住,在大多数地方(控制器,服务),正在处理事件的指令已为您调用$ apply。仅在实现自定义事件回调或使用第三方库回调时,才需要显式调用$ apply

有关更多信息,请参见