使用服务器发送事件的AngularJS

14

我有一个AngularJS应用程序,其中包含以下控制器。它可以正常使用普通的JSON资源进行GET请求和手动请求更新,但是我无法使用服务器推送事件使其工作。我面临的问题是,在我收到SSE事件并设置/更新openListingsReport变量之后,我的视图没有得到更新。我显然缺少一些非常基本的概念,请帮助我解决这个问题。

var rpCtrl = angular.module('rpCtrl', ['rpSvc']);

rpCtrl.controller('rpOpenListingsCtrl', ['$scope', 'rpOpenListingsSvc',
    function ($scope, rpOpenListingsSvc) {
        $scope.updating = false;

        if (typeof(EventSource) !== "undefined") {
            // Yes! Server-sent events support!
            var source = new EventSource('/listings/events');

            source.onmessage = function (event) {
                $scope.openListingsReport = event.data;
                $scope.$apply();
                console.log($scope.openListingsReport);
            };
        }
    } else {
        // Sorry! No server-sent events support..
        alert('SSE not supported by browser.');
    }

    $scope.update = function () {
        $scope.updateTime = Date.now();
        $scope.updating = true;
        rpOpenListingsSvc.update();
    }

    $scope.reset = function () {
        $scope.updating = false;
    }
}]);

EventSource是否与某种Web套接字(SignalR等)绑定?您不能仅将作用域函数放在Angular控制器上,并期望服务器自动向其发送请求。 - Fourth
EventSource是HTML SSE规范的一部分: https://developer.mozilla.org/en-US/docs/Web/API/EventSource服务器不是问题。我已经在客户端JS中更新了openListingsReport的值。我只是不能让AngularJS在HTML中显示更新后的openListingsReport值。 - krl
console.log($scope.openListingsReport) 给我正确的更新值!就像我说的,我已经在JS中得到了这个值。我只是不知道为什么AngularJS不会用它来更新网页。 - krl
1
我明白了,抱歉。尝试将您的$scope声明放在$apply()内部:$scope.$apply(function(){ $scope.openListingsReport = event.data;}); 参考这个链接:http://www.smartjava.org/content/html5-server-sent-events-angularjs-nodejs-and-expressjs - TrazeK
1
请注意,您很少需要调用$scope.$apply();脏检查应该处理绝大多数情况,包括此情况。 - Mawg says reinstate Monica
显示剩余2条评论
2个回答

8
问题出在以下这一行代码:
$scope.openListingsReport = event.data;

应该是:

$scope.openListingsReport = JSON.parse(event.data);

-2

如果有人正在使用AngularJS和SSE,我有一个建议。

如果你想使用服务器端事件,我建议使用AngularJS内置的$interval服务,而不是SSE。

以下是基本示例。

<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="myCtrl">

    <p>Randome no:</p>

    <h1>{{myWelcome}}</h1>

</div>

<p>The $interval service runs a function every specified millisecond.</p>

<script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function ($scope, $interval, $http) {
        $scope.myWelcome = new Date().toLocaleTimeString();
        $interval(function () {
            $scope.myWelcome = $http.get("test1.php").then(function (response) {
                $scope.myWelcome = response.data;
            });
        }, 3000);
    });
</script>

</body>
</html>

test1.php

<?php

echo rand(0,100000);

2
你所建议的是轮询,对于许多应用程序来说,这远不如基于服务器的推送架构。 - Paul Rooney
即使每个人都知道它只是一种替代方案,如果它有助于解决问题,那么也值得尝试。 - Vaibs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接