Angular.js $scope.on() не улавливает первую трансляцию при загрузке страницы

#javascript #angularjs

#javascript #angularjs

Вопрос:

По какой-то причине… при первой загрузке страницы $scope.$on('$cpuResult', cpuUpdate); первая трансляция не улавливается. Я проверил, что первая трансляция проходит успешно console.log("broadcast"); . Первая трансляция важна для инициализации данных, почему $scope.$on('$cpuResult', cpuUpdate); не улавливается первая трансляция и как я могу это исправить?

 angular.module('monitorApp')
.controller('cpuCtrl', function($scope) {
    $scope.avaiable = "";
    $scope.apiTimeStamp = "";
    $scope.infoReceived = "";
    $scope.last15 = "";
    $scope.last5 = "";
    $scope.lastMinute = "";

    var cpuUpdate = function (e, result) {
        console.log("yay");
        $scope.$apply(function () {
            $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.$on('$cpuResult', cpuUpdate);
});
  

 angular.module('monitorApp')
.run(function ($rootScope) {
    var source = new EventSource('/subscribe');

    source.addEventListener('message', function(e) {
        var result = JSON.parse(e.data);
         event = Object.keys(result)[0];
         switch(event) {
             case "cpuResult":
                 console.log("broadcast");
                 $rootScope.$broadcast('$cpuResult', result);
             break;
         }
    });
});
  

 <script src="scripts/angularApp.js"></script>
<script src="scripts/controllers/main.js"></script>
<script src="scripts/services/sse_listen.js"></script>
  

Комментарии:

1. К моменту отправки вашего первого события контроллер еще не создан. Вы можете провести рефакторинг своего приложения. запустите фабрику, которая предоставила данные, и просмотрите данные с вашего контроллера. Я понимаю, что это иронично, потому что я изначально рекомендовал вам сменить фабрику на app.run.

Ответ №1:

К моменту отправки вашего первого события контроллер еще не создан. Вы можете реорганизовать приложение, запустить его на фабрике, которая предоставляет данные результата, а затем просмотреть данные с вашего контроллера:

 angular.module('monitorApp').
factory('sseHandler', function ($timeout) {
    var sseHandler = {};
    sseHandler.result = {};
    var source = new EventSource('/subscribe');
    source.addEventListener('message', function(e) {
        var result = JSON.parse(e.data);
         event = Object.keys(result)[0];
         switch(event) {
             case "cpuResult":
                 console.log('sseHandler result change');
                 //The controller will watch the result
                 //on this object
                 $timeout(function(){
                     sseHandler.result = resu<
                 });
                 //I wrap the result change in a timeout
                 //to schedule an apply,
                 //which will trigger your watches to run
                 //their dirty checks.
             break;
         }
    });
    return sseHandler; //return the object with exposed result
}).
controller('cpuCtrl', function($scope, sseHandler) {
    $scope.avaiable = "";
    $scope.apiTimeStamp = "";
    $scope.infoReceived = "";
    $scope.last15 = "";
    $scope.last5 = "";
    $scope.lastMinute = "";

    var cpuUpdate = function (result) {
        console.log("yay");
        // You don't need the apply here anymore.
        $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;
    }
    // The second argument of the watch gets called when
    // the result of the first argument changes
    // I'm assuming timestamp changes often enough
    $scope.$watch(function(){ 
        return sseHandler.result.timestamp; 
    }, function(){
        cpuUpdate(sseHandler.result);
    });

});
  

Комментарии:

1. Любопытно… почему я не мог сохранить .run() и сделать $timeout(function(){$rootScope.$broadcast('$cpuResult', result); }, 1000); ? Я попытался сохранить .run() и таким образом, и, конечно, не сработало.

2. Вы имеете в виду $timeout(function(){$rootScope.$broadcast(‘$cpuResult’, результат);}, 1000); ? Мне кажется, что это, вероятно, сработает для меня, если ваша страница не слишком сложная, но я думаю, что использование $ watch более идиоматично.

3. Вы можете поместить сообщение журнала в инициализацию вашего контроллера и сообщение журнала в вашу трансляцию, чтобы проверить, что контроллер создан до отправки первого события.

4. Почему я не смог внедрить свой сервис как .controller('cpuCtrl', ['sseHandler', function($scope) {}]); ?

5. Это должно выглядеть как .controller(‘cpuCtrl’, [‘$scope’, ‘sseHandler’, функция ($scope, sseHandler) {}]);