AngularJS Service Implementing the Pub/Sub Design Pattern

I've been browsing for solutions to a problem and stumbled upon an answer provided by Mark Rajcok

angular JS - communicate between non-dependend services

However, I am struggling to fully grasp his explanation, particularly this part:

angular.forEach(event1ServiceHandlers, function(handler) {
            handler(some_data);
});

I'm uncertain if the event1ServiceHandlers array is filled with functions (referred to as handler) that are executed within this forEach loop.

It would be immensely helpful if someone could provide a clear example of setting up a publish/subscribe system.

I have two services that need to communicate with each other, but I want to steer away from using $rootScope.$broadcast. After researching, it seems like implementing a pub/sub service is the optimal approach. One of my services must call a function within the other service. However, due to one service being a dependency of the other, I cannot establish a mutual connection because of circular dependencies.

Therefore, my question is: If you have two AngularJS services (factories), how can service 1 trigger a function in service 2 when service 2 already depends on service 1? This should be done without utilizing $broadcast and $on.

Answer №1

Are the handlers in the event1ServiceHandlers array functions that are triggered within this forEach loop?

Affirmative

How can service 1 execute a function on service 2 if service 2 already depends on service 1?

To achieve this, introduce a new service called NotificationService:

.factory('NotificationService', [function() {
    var event1ServiceHandlers = [];
    return {
        // publish
        event1Happened: function(some_data) {
            angular.forEach(event1ServiceHandlers, function(handler) {
                handler(some_data);
            });
        },
        // subscribe
        onEvent1: function(handler) {
            event1ServiceHandlers.push(handler);
        }
    };
}])

Then, have service 2 register a callback function with the NotificationService:

.factory('Service2', ['NotificationService',
function(NotificationService) {
    // Event handler for event1
    var doSomething = function(someData) {
        console.log('S2', someData);
        // Actions to be performed here
    }
    // Subscribe to event1
    NotificationService.onEvent1(doSomething);
    return {
      // Define public API for Service2 here
    }
}])

Whenever service 1 needs to execute the doSomething() function on service 2, it can trigger the event1Happened event:

.factory('Service1', ['NotificationService',
function(NotificationService) {
    var someData = ...;
    return {
       // Define public API for Service1 here
       callService2Method: function() {
         // Trigger event
         NotificationService.event1Happened(someData);
       }
    }
}])

Answer №2

Within his illustration, the NotificationService emerges as a novel service that any preexisting services would rely upon. Although he presented an implementation of Service1, the functionality for Service2 remains essentially unchanged...both are dependent on NotificationService without either being aware of the other.

Service1 and Service2 individually subscribe to events by invoking

NotificationService.onEvent1(event1Happened);
and trigger events through
NotificationService.event1Happened(my_data);
.

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

I'm having trouble grasping the concept of this asynchronous behavior

After reviewing the output provided, my initial expectation was for working to be displayed between the lines of begin and end. Here is the rule: Is there a possible solution to achieve this outcome without modifying the app.js file? app.js const se ...

Optimizing Require.js File for Efficient Loading

I have successfully implemented require.js with multiple individual files: require(['app/login/Login'], function (app) { new app.Login(); }); Everything is functioning as expected, with each module loading when needed. Recently, I have opti ...

JavaScript Radio Buttons

Below are the different radiobuttons: Apple <input type="radio" id="one" name="apple" data-price="10" value="light"/> Light <input type="radio" id="two" name="apple" data-price="20" value="dark" /> Dark <input type="text" id="appleqty" name ...

Deleting files with a dedicated function (Dropzone.js)

I need to implement functionality that removes the uploaded file when a 'cancel' button is clicked. Here's how my HTML code looks: <div reqdropzone="reqDropzoneConfig"> <form id="requisitionupload" class="dropzone dz-clickable" ac ...

To combine both jquery-1.min.js and jquery.min.js is essential for achieving optimal functionality

When using these two files, only one of them can work on a page. <script src="jquery.min.js"></script> <script src="jquery-1.min.js"></script>//Only the second one works Alternatively, if the order is changed: <script src="jq ...

Obtain the URL value using jQuery and place it inside a <span> element

How can I insert a href value into the span tag like this? <p class="name"> <a download="adja-lo.pdf" title="adja-lo.pdf" href="http://localhost/MatrixDRSnews/apps/Matrix/server/php/files/adja-lo.pdf">adja-lo.pdf</a> </p> ...

Effortless method to handle package.json configurations

Is there a better approach for seamlessly transitioning between using npm link and git, or another solution that caters well to both front end and back end developers? The dilemma I'm facing revolves around developing a website that utilizes multiple ...

Introducing the First Angular Factory

It's high time for me to finally inject my first angular Factory . . . Here is the code I have: .factory('Debts', function($q, $scope){ return MA; }) .controller('Admin', function ($scope, Debts) { $scope.Debts = Deb ...

Button for Autocomplete Component in React Material UI to be displayed after clearing the field

After successfully adding a search button to my Autocomplete Component on Material UI, I encountered an issue where the button always appears before the clear button as shown in this image: I am seeking assistance on how to configure the InputProps so tha ...

How can function expressions result in a returned value?

Function expressions result in a value, unlike function declarations which do not. This distinction was clarified for me by others in a different SO thread (link provided). All functions default to returning undefined, hence the emphasis on "expression" ...

Access real-time information via JSON

I am facing a logical thinking challenge. Successfully retrieving data from a PHP file via JSON, but now encountering a slight issue. My goal is to retrieve various headlines - main and sub headlines. Each main headline may contain an unknown number of su ...

What is the best way to automatically adjust the size of this HTML Menu to match the width of its

I am in the process of converting a Drupal 6 theme to Drupal 7 and I'm encountering some difficulties with this particular section. Below is the HTML code snippet: <ul id="nav" class=" scaling-active scaling-ready"> <li><a href="/demos ...

The face textures are not being applied correctly to the model imported in THREE.js

I'm having trouble importing a model exported from blender using the THREEJS exporter. The model loads correctly in my scene with the materials applied, such as the car appearing yellow and the glass being transparent as intended. However, I am facin ...

Is there a way to incorporate both max-width and min-width in a matchMedia query effectively?

I'm currently utilizing the matchMedia API in my JavaScript code to identify viewports, with the goal of reducing DOM manipulations. Instead of using display: none extensively, I am opting for a v-if directive from Vue to determine when elements are ...

Enter information to accompany your images in the description box

After browsing through numerous websites tonight, I stumbled upon this code. My goal is to create a photo upload page on Google Drive and set up a dropbox for it. I'm facing an issue where the information inputted into my placeholder box (city and ye ...

A Vue computed property is returning the entire function instead of the expected value

One of my computed properties is set up like this: methods: { url_refresh: function (id) { return `${this.url_base}?start=${Date.now()}` } } However, when I attempt to print the value on mount: mounted() { console.log(this.url_refresh) ...

Struggling to access values from your model using EL in JavaScript? Let me provide some guidance

In my model, there is an object named "domain" with two methods: getDescriptionEn() and getDescriptionFr(). I am trying to retrieve the appropriate description based on the current locale. My issue lies in the following code snippet: var locale = "${cur ...

Codeigniter session unexpectedly ends after AJAX call completes successfully

Currently, I am utilizing the CodeIgniter framework on a Heroku server with an AWS database. In my AJAX success function, I have a window.location.reload(); call which ends up destroying the session and redirecting to the login page. Is there a way to prev ...

`Formatting Dates with Google Script`

I am looking to modify the date format from "mmm-dd-yyyy" (Nov-11-2019) using my existing code. Here is the code snippet: var timeStamp = data[i][timeStampappr]; var formatted = (timeStamp.getMonth()+1) + '/' + timeStamp.getDate() + &ap ...

Validating the same input in Angular Formly allows for consistent and

I am looking to create a validation process in Formly that ensures two input fields (both for email) return the same value. Currently, I have successfully implemented a check that compares the input field's value with the email field. vm.fields = [ ...