Sharing asynchronous data between AngularJS controllers

Among the multitude of discussions on sharing data between controllers, I have yet to come across a satisfactory solution for my particular scenario.

In my setup, one controller fetches data asynchronously using promises. This controller then creates a copy of the data within its scope. I also have a second controller that needs to work with the same copied data as the first controller so that they both share it.

Here is a simplified example of the code:

.controller('firstController', function ($scope, someService){
    var vm = this;
    someService.getData().then(function(data) {
        angular.copy(data, vm.data); //creates a copy and places it on scope
        someService.setCurrentData(vm.data)
    }
});

.controller('secondController', function ($scope, someService){
    var vm = this;
    vm.data = someService.getCurrentData(); //Triggers before the setter in firstController
});

.factory('someService', function(fetchService){
    var _currentData = {};

    var getData = function(){
        return fetchService.fetchData().then(function(data) { return data; });
    };

    var getCurrentData = function(){
        return _currentData;
    }

    var setCurrentData = function(data){
        _currentData = data;
    }
});

Due to the asynchronous nature of getData, the setCurrentData function may be triggered after getCurrentData, resulting in different objects being returned instead of the correct one. While solutions like broadcast and watch exist, I'm looking for an alternative method to avoid using them if possible.

Answer №1

Revamp your factory by adding a conditional to determine if the _currentData variable has been initialized - this way, you can streamline the use of callbacks:

app.factory('someService', function(fetchService){
    var _currentData = null;

    var setCurrentData = function(data){
        _currentData = data;
    }

    var getData = function(callback) {
        if (_currentData == null) {
            fetchService.fetchData().success(function(data) { 
                setCurrentData(data);
                callback(data); 
            });
        } else {
            callback(_currentData);
        }
    };

    /*
    var getCurrentData = function(){
        return _currentData;
    }
    */
});

Now, when you invoke the getData service, it will first check if the data is already available and stored. If so, it will utilize that data; otherwise, it will fetch it!

someService.getData(function(data) {
    console.log(data); //celebrate persistence!
})

Answer №2

Here is how I would approach the solution:

.controller('firstController', function ($scope, $rootScope, someService){
    var vm = this;
    someService.getData().then(function(data) {
        angular.copy(data, vm.data); // makes a copy and assigns it to scope
        someService.setCurrentData(vm.data); 
        $rootScope.$broadcast('myData:updated'); 
    }
});



.controller('secondController', function ($scope, $rootScope, someService){
      var vm = this;
      $rootScope.$on('myData:updated', function(event, data) {
         vm.data = someService.getCurrentData(); 
      });
});

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

Morris.js tutorial: Enhancing bar charts with data labels

I have this: But I want this instead: Does morris.js support this feature? If not, what would be the most effective method to implement it? ...

Interactive image rotator featuring navigation buttons for next and previous slides

I recently followed a tutorial from W3Schools Now, I am looking to enhance it by adding previous / next buttons for the indicators, rather than for the slider itself Here is what I aim to accomplish: Below is the code snippet that I have been working on ...

Is it possible to select multiple drop-down lists on a webpage using Python and Selenium?

I am encountering an issue while attempting to click on multiple dropdown lists within a page. I continuously receive an error message stating that my list object does not have an attribute 'tag_name'. Here is my code snippet: def click_follow_ ...

What is the best way to retrieve the total number of options within a dynamically generated <select> element using JavaScript in JSP?

To generate a page, I use the following code: <%List<String> someList = new ArrayList<String>(); someList = SQL();%> <select id=Select> <% for (int i =0; i < someList.size(); i++) { %> <option value=<%= someLis ...

Using a JavaScript command, connect a function from one file to another file

I attempted to import a function because I want to click on <il> servies</il> and scroll to the services section on the home page. However, I simply want to click on the li element in the navbar and scroll to the service section on the home pag ...

Retrieve all string values from an Angular POST request using Express

Here is a simple code snippet that sends a POST request to a server using express: $http.post('/blah', { boolean: true, stringBoolean: 'true', number: 213, stringNubmer: '44444444', string: 'adssd&apo ...

Which is the preferable option for creating a circular daily planner: canvas or SVG?

As a novice programmer delving into the world of coding (or at least hoping to), I have a question regarding graphic tools in html5 for my latest project. My goal is to create a planner app using electron, with the unique twist that the planner form sho ...

Deploying CSS/JS files in Magento 2 is a crucial

Hello, I recently set up magento2 with the sample data included. After attempting to deploy static css/JS using the command php bin/magento setup:static-content:deploy, I didn't receive any errors but the issue persists. Additionally, I am unable to l ...

Linking two div elements together with a circular connector at the termination point of the line

I am currently working on designing a set of cards that will showcase a timeline. I envision these cards to be connected by lines with circles at each end, for a visually appealing effect. At the moment, I have created the cards themselves but I am struggl ...

The Highchart formatter function is being called twice on each occasion

My high chart has a formatter function that seems to be running twice. formatter: function() { console.log("starting formatter execution"); return this.value; } Check out the Fiddle for more details! ...

Is there a way to select an element within a nested list item only when the preceding list item is clicked using Jquery/JavaScript?

I am working with an unordered list that looks like this: <ul> <li><a class="foo" id="one">some text</a></li> <li><a class="foo" id="two">some text</a></li> <li><a class="foo" id="thr ...

`Inquiry into AJAX form submission problem`

Here is the HTML markup and JS code for my signup page. I encountered an issue where, if I leave all text inputs blank and click submit for the first time, it validates and shows an error message. However, when I click submit a second time, it directly sen ...

Leveraging symbols as object key type in TypeScript

I am attempting to create an object with a symbol as the key type, following MDN's guidance: A symbol value may be used as an identifier for object properties [...] However, when trying to use it as the key property type: type obj = { [key: s ...

Exploring the depths of nested ng-repeat using JSON structures

I am attempting to organize a nested loop with ng-repeat but I am encountering an issue where nothing is being displayed in the nested loop. HTML: <div ng-repeat="person in persons"> <p> {{ person.name }} </p> <div ng-repeat="frien ...

What is the best way to modify an object within a pure function in JavaScript?

Currently, I am exploring different strategies to ensure that a function remains pure while depending on object updates. Would creating a deep copy be the only solution? I understand that questions regarding object copying are quite common here. However, ...

Transfer the data in the columns of Sheet1 to Sheet2 and eliminate any duplicates using Google App Script

Is there a way to transfer only unique rows from a SOURCE Spreadsheet to a DESTINATION spreadsheet? Spreadsheet #1 (SOURCE) - This sheet contains ID's and Names, but has duplicate rows. There are over 500k rows in this sheet and it is view-only. Spre ...

Trouble with image click event in jQuery/JavaScript

I am having trouble with my HTML and JS code. I have added images to my HTML page and want to make it so that when the image is clicked, an alert box pops up. However, for some reason, my JavaScript isn't working as expected. Here is a snippet of my ...

Running Python script in Node.js and pausing until completion

I am currently working on an API-Rest project using Node.js, where I need to run a python script that will create a .json file and store it in a specific directory. My goal is to wait for the python script to finish executing so that Node.js can access the ...

The function Amplify.configure does not exist

Currently attempting to utilize AWS Amplify with S3 Storage, following the steps outlined in this tutorial for manual setup. I have created a file named amplify-test.js, and here is its content: // import Amplify from 'aws-amplify'; var Amplify ...

Is there a way to ensure that a method is always called in JavaScript after JQuery has finished loading

We recently integrated jquery load into our website to dynamically load content into a div without refreshing the whole page. However, we've noticed that in the complete function, we have to constantly re-apply various bindings. Is there a way to set ...