Storing data in cache and refreshing another object for a chart does not function properly

When working in my Controller, I am retrieving data from a $resource object that is stored in a caching service.

$scope.data = myService.query(); //myService caches the response. 

Within the same controller, I am setting up the configuration for a chart (for the GoogleChartingDirective).

$scope.chart = {
      'type': 'AreaChart',
      'cssStyle': 'height:400px; width:600px;',
....
      'rows' : convert($scope.data),
...
}

The function 'convert' simply takes the data from myService and transforms it into an array suitable for the chart.

This setup works only if the response of the query has already been cached (If I navigate away and then back, the graph appears, but not when accessing the route directly).

I suspect the issue may lie with my caching method?

angular.module('webApp')
  .service('myService', function myService($cacheFactory,res) {
    var cache = $cacheFactory('resCache');

   return {
      query: function() {
         var data = cache.get('query');
         if (!data) {
            data = res.query();
            cache.put('query', data);
         }
         return data;
      }
   };

});

I attempted to use $scope.$watch in my Controller. It was triggered only once without any data. However, when I switch routes and then return, it triggers again, this time with the data present.

$scope.$watch('data',function(newValue){
      console.log("Watch called " + newValue);
}

It seems like there might be an issue with the $watch event not being properly activated.

If I manually trigger a refresh using a button, the $watch event fires and the data displays as expected.

$scope.refresh = function(){
      $scope.data = $scope.data.concat([]);
}

As someone new to AngularJS, I am exploring through a small demo project and seeking guidance on resolving common challenges.

Do you have any suggestions on how to overcome this problem?

Answer №1

It seems like the issue at hand is that there may be a lack of awareness regarding the asynchronous nature of the res.query() call. When using the $resource service, the query function immediately returns an empty array for data. This array will then be populated with the actual data once it is retrieved from the server. If your $watch is triggered when the empty array is assigned to your $scope.data, you can address this by utilizing the $watchCollection function.

$scope.$watchCollection('data', function(newNames, oldNames) {
  var convertedData = convert($scope.data);
  ...
});

Your cache functionality appears to be functioning correctly. Upon making another server call in the future, you should receive the array with all the updated data. Additionally, the $resource service includes a built-in caching option, eliminating the need for a custom cache implementation.

You may wonder why the $resource service operates in this manner - returning an empty array first and then populating it with data. This design aligns with Angular's framework principles. For instance, if you were to use the data in an ng-repeat, the information would automatically reflect in the view due to ng-repeat monitoring your collection. It’s possible that your chart component functions similarly to traditional JavaScript (such as jQuery), which might not actively watch your data changes.

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

Does JavaScript sort dictionaries automatically?

Here's an issue we're facing: when the ajax script receives a dictionary from the server, the order changes: The server sent this: {753: 'Wraith', 752: 'Phantom Extended', 751: 'Phantom', 750: 'Ghost Extended&a ...

Using AngularJS and ChartJS together for stellar data visualization

I need help displaying the canvas element within custom angular directives. Being new to AngularJS, I am in search of a demo or idea regarding Chart.js integration with AngularJS. Important: I specifically require a custom directive for chart display. T ...

Ways to extract text from a temporary element

Here is my HTML code: <div class="p-login-info" ng-show="loggedOut()">My text.</div> This is the corresponding JavaScript code: var e = element(by.className('p-login-info')); e.getText() .then(function(text){ var logoutText = ...

Unable to click, but can only be activated by touchstart or mousedown

Is it possible to bind a 'click' event to a paragraph? Here is the function I am using: $(document).on('touchstart mousedown',"p span.text", function(e) { console.log('I was clicked'); *more code here* }); When I ...

Tips for converting Javascript require to Typescript import using the const keyword

Recently, I've been attempting to import faktory_worker_node from github.com/jbielick/faktory_worker. The README provides the following instructions: const faktory = require('faktory-worker'); faktory.register('ResizeImage', asyn ...

Ways to ensure the first div always expands when sorting in AngularJS

In my AngularJS application, I have a set of div elements generated using ng-repeat. The first div is always expanded by default upon loading the page. Now, when I click a button to sort the divs based on their ID in the JSON data, I want the top div to ...

Mastering the Art of Unit Testing JavaScript Asynchronous Code with Jasmine Mocking

Hello, I recently started learning JS and encountered a problem while testing asynchronous methods with jasmine mocking. Below is the code snippet I am trying to test: test.factory('service', ['$http', '$q', function($http, ...

A dynamic AJAX menu showcasing content in a dropdown format, away from the conventional table layout

My dropdown select menu is correctly populating with data, but the output always appears outside of the table. Can anyone spot the issue in my code? Any suggestions or ideas are greatly appreciated! Thanks in advance, select.php <?php $q = $_GET[&apos ...

What is the best way to populate dropdown menus using JavaScript?

I'm facing an issue with my ajax request where I am unable to populate the options of a select tag. This problem is occurring in multiple blocks where the select tag serves the purpose of choosing a type of product. Here is how my select tag looks li ...

Making a synchronous call to a web API using JQuery

Understanding JQuery promises and deferred objects has been a bit of a challenge for me, so please bear with me. I should also mention that my application is built using React, Typescript, and ES6. Let's imagine we have an array of objects: [{ Objec ...

What causes nodejs to exit prematurely without running all the code?

When running the code provided, it randomly prints "DONE" or not. Can you explain why this happens? How can I ensure that it always reaches the console.log("DONE"); line every time? const {Worker, isMainThread, parentPort} = require('node:worker_threa ...

Revamp the Twitter button parameters or alter its settings

I'm working on a web page that includes a Twitter button. Before the button, there is an input field and a form where users can easily add relevant hashtags for the page. The goal is to take the text from the input field and populate it in the Twitter ...

Stopping npm private organization from releasing public packages

Is there a method to restrict the publication of public packages within an npm organization? It appears that this scenario would often arise (ensuring that no member of an organization accidentally publishes a package as public when it should be private b ...

Revising text for real-time editing

Most of us are familiar with the functionality on StackOverFlow that allows you to preview your text before posting a question. I'm interested in implementing a similar feature on my website and am looking for some guidance on how to get started. I ...

Using Q to conduct polling asynchronously with promises

I am facing a situation similar to the one discussed in this blog post: Polling with promises. The author explains using promises for polling until a JobID is returned. I intend to implement this using Q. I want to chain promises together but my attempts ...

Svelthree - What is the best way to incorporate edges and lines into a scene?

I'm currently experimenting with adding edges to an object in Svelthree. While I understand how to incorporate a geometry into a scene using mesh, I'm unsure of how to include lines at the edges of the geometry. Referencing the official REPL tu ...

What is the process by which JavaScript evaluates the closing parenthesis?

I'm currently working on a calculator project that involves evaluating expressions like (5+4). The approach I am taking is to pass the pressed buttons into an array and then create a parse tree based on the data in that array. One issue I'm faci ...

Discovering how to create a line break within a text area using the $scope feature in Angular

I'm looking to incorporate a text area for chat input that is resizable. I would like to have some pre-filled texts in it, such as: Hi Jhon, Thanks for contacting us.... I want the text to appear on a new line after the existing content in the textar ...

The primary view seamlessly integrates with the page following the invocation of the partial view

Whenever the button is clicked, a different partial view is returned based on the selected value from the drop-down list. Controller: [HttpPost] public ActionResult Foo(SomeViewModel VM) { var model = VM; if (Request.IsAjaxRequest()) { ...

Developing a TypeScript NodeJS module

I've been working on creating a Node module using TypeScript, and here is my progress so far: MysqlMapper.ts export class MysqlMapper{ private _config: Mysql.IConnectionConfig; private openConnection(): Mysql.IConnection{ ... } ...