Javascript Angular.js-在工厂/服务中设置超时以延迟事件侦听器

Javascript Angular.js-在工厂/服务中设置超时以延迟事件侦听器,javascript,angularjs,Javascript,Angularjs,当客户端第一次启动时,我试图延迟广播的第一次迭代,直到控制器中的$watchCollection准备好捕捉它。但是,setTimeout()并不能解决这个问题,也不能使它成为一个完全没有eventlistener的地方。使用$timeout尝试此操作,结果相同。为什么会这样 angular.module('monitorApp') .factory('sseHandler', function ($rootScope) { var source = new EventSource('/s

当客户端第一次启动时,我试图延迟广播的第一次迭代,直到控制器中的
$watchCollection
准备好捕捉它。但是,
setTimeout()
并不能解决这个问题,也不能使它成为一个完全没有eventlistener的地方。使用
$timeout
尝试此操作,结果相同。为什么会这样

angular.module('monitorApp')
.factory('sseHandler', function ($rootScope) {
    var source = new EventSource('/subscribe');
    var sseHandler = {};
    setTimeout(function() {
        source.addEventListener('message', function(e) {
            $rootScope.$apply(function (){
                result = JSON.parse(e.data);
                event = Object.keys(result)[0];
                switch(event) {
                    case "cpuResult":
                        sseHandler.result = result;
                    console.log(sseHandler.result.cpuResult.timestamp);
                    break;
                }
            });
        });
        return sseHandler;
    }, 1000);
}); 
编辑: 我把它放在我的节点服务器上,当客户端连接时,SSE广播会立即发送给它。服务
source.addEventListener
成功捕获第一次广播。但此时控制器尚未就绪,
$scope.$watchCollection
将错过第一次广播

angular.module('monitorApp')
.controller('cpuCtrl',   ['$scope', 'sseHandler', function($scope, sseHandler) {
    var cpuUpdate = function (result) {
        $scope.available = result.cpuResult.avaiable;
        $scope.apiTimeStamp = result.cpuResult.timestamp;
        $scope.infoReceived = new Date();
        $scope.last15 = result.cpuResult.metrics['15m'].data
        $scope.last5 = result.cpuResult.metrics['5m'].data
        $scope.lastMinute = result.cpuResult.metrics['1m'].data
    }
    $scope.$watchCollection(function(){
                 return sseHandler.result; 
    }, function(){
        if (sseHandler.result.cpuResult) {
            console.log("yes");
                 cpuUpdate(sseHandler.result);
        }
    });
}]);

这边怎么样?工厂将正常返回对象。$timeout之后,将设置侦听器,并且返回的对象通常应填充数据

angular.module('monitorApp')
.factory('sseHandler', function ($rootScope, $timeout) {
    var source = new EventSource('/subscribe');
    var sseHandler = {};
    $timeout(function() {
        source.addEventListener('message', function(e) {
            $rootScope.$apply(function (){
                result = JSON.parse(e.data);
                event = Object.keys(result)[0];
                switch(event) {
                    case "cpuResult":
                        sseHandler.result = result;
                    console.log(sseHandler.result.cpuResult.timestamp);
                    break;
                }
            });
        });
    }, 1000);
    return sseHandler;
}); 
如果您希望(出于任何原因)在
sseHandler
连接到服务器时实例化控制器并准备好执行操作,最可靠的方法是在
sseHandler
上使用
init()
connect()
方法,并让控制器在准备好时调用它

例如:


你不能耽误这样的服务。超时回调的返回值被忽略。你应该改用承诺……我如何将“一旦控制器完成/实现”包装成承诺?不清楚你想要实现什么。为什么要延迟设置服务的属性,因为控制器可以随时访问它。最可能的意思是,您希望延迟控制器访问属性,直到属性被设置,但这不是必需的(特别是如果您使用
$watch
)。请澄清您试图实现的目标,这样我们就不会追踪鬼魂:)请查看原始消息中的编辑。您不能发出“watchcollection ready”之类的事件,然后在该事件发生时广播吗?显然只有一次。
.factory('sseHandler', function ($rootScope) {
    var sseHandler = {};

    sseHandler.init = function () {
        var source = new EventSource('/subscribe');
        source.addEventListener('message', function (evt) {
            $rootScope.$apply(function () {
                result = JSON.parse(evt.data);
                event  = Object.keys(result)[0];
                switch (event) {
                    case "cpuResult":
                        sseHandler.result = result;
                        console.log(sseHandler.result.cpuResult.timestamp);
                        break;
                }
            });
        });
    };

    return sseHandler;
})

.controller('cpuCtrl', function ($scope, sseHandler) {
    function cpuUpdate(result) {
        $scope.available    = result.cpuResult.avaiable;
        $scope.apiTimeStamp = result.cpuResult.timestamp;
        $scope.infoReceived = new Date();
        $scope.last15     = result.cpuResult.metrics['15m'].data
        $scope.last5      = result.cpuResult.metrics['5m'].data
        $scope.lastMinute = result.cpuResult.metrics['1m'].data
    }

    $scope.$watchCollection(function () {
        return sseHandler.result;
    }, function () {
        if (sseHandler.result && sseHandler.result.cpuResult) {
            console.log("Yes !");
            cpuUpdate(sseHandler.result);
        }
    });

    // Now that everything is set up, let's initialize `sseHandler`
    sseHandler.init();
});