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

The current object is not being referenced by this specific keyword

I am encountering an issue in my React application where I am trying to set the state of a child component using this.props, but it is showing an error saying props is undefined. It seems like 'this' is not referencing the current object correctl ...

The HTML5 video will continue playing indefinitely as long as its readyState remains at 4

In my efforts to develop a personalized HTML5 video player that can handle live streaming, recording of live streams, and playing regular video files, I have run into an issue with creating a custom seeking bar. To achieve this, I implemented the following ...

What is the best way to organize properties within the Class Variance Authority?

Can the following be achieved in CVA? const mathPanelVariants = cva( 'relative mt-[100px] w-full rounded-sm border-l-[3px] px-[24px] py-[16px]', { variants: { variant: { theorem: { box: 'border-l-[#617bff] dark:bg-[#182 ...

Can the functionality of ngIf and async pipe be replicated within the component's code?

With a form component and a thank you page, I am faced with the challenge of sharing data between these two components using rxjs ReplaySubject. The full code listings can be found here. In my implementation, I am utilizing ngIf and the async pipe to hand ...

PHP issues caused by Ajax form compatibility

I'm currently working on developing an upload website and I've encountered some challenges while trying to implement an upload progress bar. The Ajax form in my scripts seems to be causing issues with the PHP code, preventing the file from being ...

Using callback functions in a JavaScript AJAX request

I am currently working on a function to handle an Ajax request with a callback. The main goal of this code is to send a request and display the response within a div element on my HTML page. However, I have been facing issues with the callback functionalit ...

Error: The property 'scrollIntoView' cannot be read because it is null

class MessageApp extends Component { constructor(props) { super(props) this.state = { text: "", messages: [] } } componentDidMount() { const config = { apiKey: "<api-key>", authDomain: "<projec ...

What could be causing the malfunction of client components in NextJS 13.3.0 with experimental features?

My understanding of the beta documentation suggests that I need to include "use client" at the top of my client component in order for it to be defined as such. This allows me to use it within server components, leaves, or layouts. With that in ...

Using $route to obtain URL parameters

I am faced with the challenge of passing the last parameter from the following URL to a $http.get request in my Angular application. http://myurl.dev/users/32 However, I am struggling to figure out how to pass the 32 as the id. Here is what I have tried ...

Exploring the capabilities of data processing in Node.js

I've been attempting to read data from a locally stored JSON file, organize it into individual JS objects, and add them to a queue. However, I'm struggling to find a way to test my parsing function to ensure it's functioning correctly. My cu ...

Using the preselection feature in the MUI DataGrid can cause the grid to become disabled

I am customizing a mui datagrid to have preselected rows using the following code snippet: const movieCrewList = movieCrew.map((item) => item.id); const [selecteTabledData, setSelectedTableData] = React.useState([]); <DataGrid rows={crewData} c ...

InvalidTypeError: The function 'state.map' cannot be applied

import React from "react"; import { useContext, useEffect, useRef, useState } from "react"; import noteContext from "../Context/notes/NoteContext"; import Addnote from "./Addnote"; import Noteitems from "./Notei ...

Issues with debuggers in Chrome and Firefox with AngularJS are causing frustration for developers

Currently, I am in the process of developing a hybrid application that combines AngularJS with Angular 8. As part of my testing procedure, I am attempting to debug the application. However, I have encountered an issue where the debuggers function properly ...

What is the best way to style a value within a v-for loop inside an el-option element in Element UI?

I'm looking for a way to format the value in label(item.value) as a decimal within a v-for loop. Below is my code snippet: <el-form-item :label="label" :required="required" prop="Jan"> <el-select v-model=& ...

I am currently working on obtaining images that are saved by their URL within a PHP file. These images are located within a directory named "images."

My code is incomplete and not functioning as expected. $.get("museums.php",function(data,status){ var response=''; //console.log(data); var json = $.parseJSON(data); museums = json.museums; for(let m in museums) { $("#na ...

Adding information to an array within a document in a MongoDB database

I am facing an issue where I am trying to add data to the readBook array in my User collection document. The code and console.log seem to indicate that the User is retrieved from the database and there is data to push, but nothing changes after the code ex ...

Transforming precise military time using Angular and Javascript filtering

There are a few times where I find myself liking 01:45 //and 15:00 I believe this time format is HH:MM in military time? While I have come across some advanced functions that can parse sentences and even include seconds like HH:MM:SS, I am looking for a ...

Pass an array of links from the parent component to the child component in Vue in order to generate a dynamic

I am currently working on building a menu using vue.js. My setup includes 2 components - Navigation and NavLink. To populate the menu, I have created an array of links in the App.vue file and passed it as props to the Navigation component. Within the Navig ...

Utilize a dual-color gradient effect on separate words within the <li> element

I am attempting to display the fizz buzz function in an unordered list, with each word being a different color ('fizz'-- green, 'buzz'--blue) as shown here: I have successfully displayed "fizz" and "buzz" in their respective colors ind ...

Establishing the Time-to-Live (TTL) with Redis-OM and Node Object Mapping

Recently, I stumbled upon the exciting new Redis-OM Node Object Mapping feature. Although I have limited experience with Redis, I am eager to dive into it now. Currently, I have a basic function in place for creating rooms but I want these rooms to automa ...