Stream data's modification to numerous controllers post ajax loading

One issue I encountered in my Angular app is related to the asynchronous loading of data from a server. Some controllers depend on this data, which is retrieved through an AJAX request. The problem arises because controllers end up pointing to an empty array initially and then get replaced with the actual loaded data after the AJAX request completes. The service maintains the correct pointer to the array, but the controllers do not automatically update.

In the code snippet below, you can see how this problem manifests:

angular.module('someApp')
.factory('operationService', ['$http', function($http){
    var operations = [];

    $http.get('some-link').success(function(data){
        operations = data;
    });
  
    return {
        getOperations: function () {
            return operations;
        }
    };
}])
.controller('SomeController', ['$scope', 'operationService', function($scope, opService){
    $scope.operations = opService.getOperations();
}]);

I am looking for advice on the best practice to ensure that all parts of the Angular app have access to the most up-to-date data without resorting to cumbersome methods like manual array manipulation with "splice" and "push".

Answer №1

There are various methods to ensure only one HTTP call is made, but the options are limited due to the software versions being used.

One approach is to utilize a promise or configure your HTTP request to be sent only once. However, this feature is available in later versions of Angular. It's recommended to check the version you are using.

When it comes to best practices, utilize what your stack permits. There isn't a singular way to achieve a task. Best practices for asynchronous operations include utilizing callbacks, promises, HTTP settings, and most importantly, implementing what works within your current stack setup.

The factory code below implements a unique method to handle multiple callbacks for the same data. Subsequent calls to the factory will be added to the callbackStack until the initial HTTP request returns with the data. At that point, each callback will be triggered to retrieve the data.

angular.module('someApp').factory('operationService', ['$http', function($http){

  var callbackStack = [];
  var firstCallMade = false;
  var factoryServerData;

  return {
    getOperations: getOperations
  };

  function getOperations( ctrlCallback ){
    callbackStack.push( ctrlCallback );
    if( firstCallMade ){ return; }
    firstCallMade = true;
    getOperationsHttpRequest();
  };

  function getOperationsHttpRequest(){
    $http.get('some-link').success( factoryCallback );
  }

  function factoryCallback( operations ){
    // Handle !operations here if necessary.
    factoryServerData = operations || null;
    callbackStack.forEach( giveCtrlCallbackResponse );
  }

  function giveCtrlCallbackResponse( ctrlCallback ){
    ctrlCallback( factoryServerData );
  }
}]);

By incorporating a callback in each controller, you can ensure that the response from the HTTP call is received. Even if an empty array is returned, it will be due to the server's response and not asynchronous issues with controller loading.

.controller('SomeController', ['$scope', 'operationService', function($scope, opService){

  opService.getOperations( getOperationsCallback );
  // The $scope.operations will wait until the server responds.

  function getOperationsCallback( response ){
    $scope.operations = response;
  }
}]);


.controller('SomeOtherController', ['$scope', 'operationService', function($scope, opService){

  opService.getOperations( getOperationsCallback );
  // The $scope.operations will wait until the server responds.

  function getOperationsCallback( response ){
    $scope.operations = response;
  }
}]);

NOTE: If nested controllers are being used, the first controller can initiate the call and then broadcast the results to all nested controllers as well. This can be captured using scope.$on....

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

It appears that Apexcharts is not compatible with React/Next.js

Issue Encountering a crash in my Next.js/React/Node application whenever I utilize import Chart from "react-apexcharts" in any file. Upon attempting to access the app, an error message is displayed: Server Error ReferenceError: window is not ...

Preserving variable scope in JavaScript even after defining a function

I am facing an issue with my JavaScript code that involves invoking a function within a function: var obj = { // returns the function with prevent default prepended. run: function(functor, context){ return function(e){ e.preventDefault(); ...

The placement of the React.js/Next.js Loader is incorrect on the page

While I was trying to display a Loader over everything during data fetching from my API, I encountered a situation where the Loader was not appearing at the expected top level but inside the page itself. Even though the HTML tree showed it at the top level ...

When attempting to utilize a global variable in a POST request, it may be found to

My dilemma is that I can successfully access the global variable in other requests such as 'GET', but it becomes undefined when used in a 'POST' request. var dirName; app.post("/addFace", function (req, res) { //create directory con ...

Merging two arrays with lodash for a seamless union

Here are two arrays I'm working with: arr1 = [ { "key1": "Value1" }, { "key2": "Value2" }, { "key3": "Test3" }, { ...

The Rails application is loading JavaScript three times

I am encountering an issue with my ajax function where it is being triggered multiple times upon click instead of just once. $(document).on('click', '.newGameItem', function() { console.log('start click event'); var a ...

Discovering the clicking actions on PDF elements within an HTML environment

I am currently working on developing a web application that involves rendering various pdf objects. My main goal is to be able to detect the position of a click inside the pdf container. However, it seems like the OnClick event is not functioning as expe ...

Unable to persist the $rootScope value upon refreshing the page

Recently, I started working with angularJS on a project that involves switching between multiple languages. However, I encountered an issue where after changing the language and refreshing the page, it reverts back to the default language (English). Can an ...

Use AngularJS to synchronize items on the same row based on user input in the first column

<td align="center"><input type="number" name="test" ng-model="item.qty" ng-model-options="{ updateOn: 'blur' }" ng-change="Save(item.qty, item.qty2, item.include, {{$index}})" /></td> <td align="center"><input type="n ...

Setting all values to NULL in a struct array within another struct array in C

I have a scenario where I need to create an array of A structs, each containing an array of 50 B structs. To achieve this, I plan to use double pointers. struct A{ char* a_word; struct B** b_list; }; struct B{ char* b_word; int b_value; }; ...

What other options are available for achieving the same functionality as FormData.delete() given its low level of support?

When building my website, I utilized the FormData.delete() method to exclude specific form fields before sending data to the server. However, I encountered a setback as this method is not supported on various browsers, including Safari. Therefore, I am in ...

What techniques can be employed to utilize multiple JavaScript files?

Hey there, I am facing an issue while trying to execute multiple JavaScript codes. My first script is running smoothly with the change function, but the second one seems to be causing some trouble. Can anyone guide me on how to effectively run multiple J ...

What sets npm run apart from npm start?

Our repository contains a substantial amount of TypeScript code that we can compile and execute using "npm run dev." This setup enables us to access the test JavaScript code via localhost. However, when examining the code in the Chrome debugger, approxim ...

Angular's implementation of deferred only displays the final value in the loop

I've created a personalized synchronization process that queues up all my sync records in sequence. When my service retrieves multiple sync records, it processes them and updates the last sync date for successful records, or logs errors for failed rec ...

What is the best way to successfully implement multiple post requests using Django and Ajax on a single webpage?

After spending the entire day struggling with this issue, I am still unable to make any progress. Let me explain my predicament. In my Django form, I have two fields: redirect_from and redirect_to. The form contains two buttons: Validate and Save. Initial ...

The simplest method to retrieve Json or a Collection using Meteor's Iron Router

Currently, I am in the process of creating a set of routes. Below are some examples: / - This route should render the home page template /items - This route should display the items page template /items/weeARXpqqTFQRg275 - This route is set to return an ...

Methods for updating the value of a `<select>` element in an AngularJS controller

Within my HTML code, I have a select element with options ranging from 1 to 10: <select id="selVal" ng-model="product.quantity" ng-options="o as o for o in quantityValues" ng-change="updateDelta(product.quantity, {{product.quantity}}, product.selec ...

sorting an array using key and value criteria

How can I use Underscore.js to filter an array based on a specific key and value? Currently, my code searches for all fields' values, but I only want to search based on the key and value. Can you provide guidance on how to achieve this using Underscor ...

An unexpected hiccup occurred in the processing of the Ionic action! We are now working to

While working on my project for Android, I encountered an issue when running "ionic build android" or "ionic emulate android." The error message displayed was as follows: Error during processing of action! Attempting to revert... Error: Uh oh! Invalid Ver ...

Is there a way to insert a row into a datatable without needing to perform an Ajax reload or using the

When using row.add(…) on a datatable, I encounter an issue where it refreshes via an ajax call when draw() is activated. This leads to the new row not being visible because the data is reloaded from the database. The UX flow behind this scenario is as f ...