Delaying event listeners in Angular.js by using setTimeout within a factory or service

In order to delay the first iteration of the broadcast until the controller's $watchCollection is ready, I attempted using setTimeout() but it did not work as expected. Even trying with $timeout yielded the same result. What could be causing this issue?

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);
}); 

EDIT: After investigating further, I discovered that when a client connects to the node server, an SSE broadcast is immediately sent. While the Service source.addEventListener successfully captures this initial broadcast, the controller is not prepared at that moment which causes $scope.$watchCollection to miss the first broadcast.

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);
        }
    });
}]);

Answer №1

If you prefer that the controller is created and prepared to perform tasks as soon as sseHandler connects to the server, the best approach is to have an init() or connect() method on sseHandler and have the controller execute it when it's ready.

For example:

.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);
        }
    });

    // Initialize `sseHandler` now that everything is configured
    sseHandler.init();
});

Answer №2

Have you considered this approach? The factory will initially return an empty object. Then, after the $timeout period, a listener will be set up to populate the object with data.

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;
}); 

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

creating a countdown timer for the carousel

While experimenting, I decided to create a basic carousel from scratch. Initially, I used onclick="function()" to cycle through the images. Later on, I attempted to replace it with onload="setInterval(function, 4000)", but it seems like something went wron ...

Which function is most suitable for verifying if the values from req.param are NaN and assigning a new value if they are found to be NaN?

Regarding the about page: I'm currently working on a react app that sends URL parameters to the backend server. The frontend URL looks something like this: maxprice=100000&minsqm=50&maxsqm=100&page=1, which are the user's filters for ...

Adjust the image to stretch and crop appropriately to perfectly fit the specified dimensions

I have a div with an image inside of it, and the overflow of the div is set to hidden so that the image will be cropped if it exceeds the width or height. It was working correctly, but sometimes it doesn't. What could be causing this issue? Here is th ...

Directive fails to trigger following modification of textarea model

There is a block of text containing newline separators and URLs: In the first row\n you can Find me at http://www.example.com and also\n at http://stackoverflow.com. The goal is to update the values in ng-repeat after clicking the copy button. ...

ways to assign local file path as image url in json

Hey there, I am a new tool for angularjs. Take a look at the json file below: [ { "name": "WORLD", "population": 6916183000, "flagurl":"C:\xampp\htdocs\selva \Flag_of_the_People's_Republic_of_China.svg" }, { "na ...

Trigger the onclick method by selecting an icon within the MUI DataGrid

Currently, I am utilizing the default MUI Dialog model in the "DialogModel.js" component. Additionally, I have integrated another MUI DataGrid component as shown below: // RulesTable.js import * as React from 'react'; import { DataGrid } from &a ...

Converting JavaScript code from storeEval to executeScript_Sandbox in Selenium IDE using Kantu Ui.Vision

Looking for assistance with converting two snippets of Javascript code to extract date and time in a specific format, transitioning from storeEval to executeScript_Sandbox for use in Selenium Ide Kantu Ui.Vision. Due to recent updates, storeEval is now de ...

Doubt surrounding the behavior of Node.js when a file is required that does not export anything from a module

My understanding of Node.js' require() function and module.exports is high-level, but I still find some behaviors confusing. Imagine I have two simple one-line files named a.js and b.js. In a.js: require('./b.js'); and in b.js: console. ...

Enforcing Single Menu Accessibility in React: Only One Menu Open at a Time

Just starting out with React and JavaScript, so please bear with me for any formatting issues or lack of knowledge on best practices. I'm using Tailwind UI for my website, which includes navigation menus that require JavaScript to open and close. I h ...

Enable vertical scrolling on the second row of a table while keeping the first row fixed as the table header (CSS)

While embedding the Ace Editor in a Chrome popup window, I encountered a challenge. My goal was to keep the first row of text always visible at the top while allowing the rest of the Editor to fill the screen. However, there is an issue with a vertical scr ...

Guide on transmitting information to an API with Vue.js

Here is an example of my API call: this.$http.post("{{ route('shop.checkout.save-order') }}", {'_token': "{{ csrf_token() }}"}) .then(function (response) { if (response.data.success) { if (response.data.redirect_url) { windo ...

Currently, I am compiling a list of tasks that need to be completed, but I am encountering a dilemma that is proving difficult to resolve

Recently delved into the world of Javascript and encountered a roadblock that I can't seem to overcome. Here's the snippet of code causing me trouble: add = document.getElementById("add"); add.addEventListener("click", () => { console.log("Ple ...

Running into trouble importing an ES module in Node.js during a migration

Currently, I am in the process of developing a straightforward application for my personal project using ExpressJS. To manage database changes, I have opted to utilize sequelize ORM. My current objective is to rollback a migration, and to achieve this goal ...

Using the result of one function in another function when using async await

I am facing an issue with running a function based on the return value of another function: // in utils.js methods:{ funcOne(){ // do some thing return true } } //in component.vue methods:{ funcTwo(){ let x = this.funcOne() if(x){ ...

Creating a dynamic onclick function that depends on a variable passed from a while loop in PHP

If you're familiar with PHP, I have a scenario for you. Let's say there's a list of items generated using a while loop in PHP. Each item has a sub-list that should only appear when clicked on. I tried using the onclick function in jQuery but ...

The findByIdAndUpdate() function lacks the ability to modify the collection

I'm encountering an issue when trying to update a product using mongodb and redux. It seems that the database is not reflecting the changes after I attempt to update the product. Can someone please assist me with this problem? Here is my product.js f ...

Firebase User Becomes Undefined Upon Refreshing the Web Page

My situation is quite straightforward. I have developed a Firebase web application and I am logging in with my Google account. The problem arises when I have to keep logging back in every time the page is refreshed, as depicted in these steps: Initialize ...

Resolving label overlapping issue in Chart.js version 2

I am currently utilizing Chart.js 2 for a project of mine. I've successfully customized the style, but there's one persistent issue that I can't seem to resolve and it's becoming quite frustrating. Occasionally, the last label on the x ...

Undefined result from AngularJS $http

I encounter an error message stating "TypeError: Cannot call method 'get' of undefined" while executing this module: angular.module('EventList', []) .config([ '$routeProvider', function config($routeProvider){ $routeProv ...

The perplexing actions of Map<string, string[]> = new Map() have left many scratching their heads

I encountered an issue while trying to add a value to a map in my Angular project. The map is initially set up using the following code: filters: Map<string, string[]> = new Map(); However, when I attempt to add a value to this map, it starts displa ...