Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for clearing factories on state change in AngularJS (1.x)

I have a very large app that queries huge amounts of data (as a requirement) across dozens of projects. Each project tracks different data from other projects and each has it's own parent state/resolve (using ui-router). I can keep the data utilization low on a single page through various tricks but what I'm curious about is what is the best practice and most performant method for clearing out data on state transition in factory singletons that are no longer needed?

Essentially, I need all the other singletons not in use by the current state to empty on state transition so the browser doesn't overflow due to the data size.

As a work around, I'm currently passing data through all my factories and not storing it directly in it's originating factory. Instead, I'm resolving in a sort of façade pattern which queries the data from seperate data definition factories and routing all of the resolved data to a single global storage factory for consumption by view directives like so.

angular.module('someModule', [])
.config(function($stateProvider){
   $stateProvider
   .state('state1', {
      resolve: {state1Data: function(facadeFactory){return facadeFactory.setState1()}}
   })
   .state('state2', {
      resolve: {state2Data: function(facadeFactory){return facadeFactory.setState2()}}
   });
})
.factory('facadeFactory', function facadeFactory($q, singleStorageFactory, dataSource1, dataSource2, dataSource3, dataSource4){
   var factory = {};
   factory.setState1 = function(){
      var dfd = $q.defer();
      dataSource1.getAllData()
      .then(function(result){ return dataSource2.getAllData(result);})
      .then(function(result){ return singleStorageFactory.setData(result);})
      .then(function(){dfd.resolve(true);});
      return dfd.promise;
   }

   factory.setState2 = function(){
      var dfd = $q.defer();
      dataSource3.getAllData()
      .then(function(result){ return dataSource4.getAllData(result);})
      .then(function(result){ return singleStorageFactory.setData(result);})
      .then(function(){dfd.resolve(true);});
      return dfd.promise;
   }
   return factory;
})
.factory('dataSource1', function dataSource1(){
   var factory = {};
   factory.dataDef = {
      name: "list1",
      cols: ['col1','col2','col3'],
      thisKey: 'col1'
   };
   factory.getAllData = function(currentData){
      // get data > add it to currentData if it exists > return aggregated data
   };
   return factory;
})
// dataSource2, dataSource3, and dataSource4 are same as dataSource1 albeit with different data definition
.factory('singleStorageFactory', function singleStorageFactory($q){
     var factory = {};
     factory.data;
     factory.setData = function(data){
          var dfd = $q.defer();
          factory.data = data;
          dfd.resolve(factory.data);
          return dfd.promise;
     };
     return factory;
});

I'm storing the individual data definitions in their own factories due to some other requiements relating to aggregating parts and peices of data across projects into a master tracker of sorts but that's neither here nor there.

Bottom line, Is this the right way to keep large datasets from crashing the browser on state transition or am I missing something obvious about how AngularJS garbage collects from singletons not in use?

like image 897
Josey Avatar asked Nov 07 '22 00:11

Josey


1 Answers

We have considered this at my office, and could not find any true way of saving data draw, especially when the data is large.

We resulted in doing a page refresh every 5-10 minutes, while its not 100% live data this works for us.

$timeout(reload, 300000);// don't forget to inject $timeout in your controller

reload(){
$route.reload(); // don't forget to inject $route in your controller
}
like image 149
Tom Edwards Avatar answered Nov 11 '22 18:11

Tom Edwards