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












4















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?










share|improve this question




















  • 1





    Use a LRU cache such as $cacheFactory.

    – georgeawg
    Nov 20 '18 at 18:35











  • BTW the facadeFactory.State[12] methods are deferred anti-patterns and there is no need to manufacture promises for resolver functions as they accept both promises and synchronous variable.

    – georgeawg
    Nov 20 '18 at 19:53











  • @georgeawg Thanks. I'm looking into the $cacheFactory but I'm not sure it will solve the problem at hand; will experiment more.

    – Josey
    Nov 20 '18 at 20:13











  • @georgeawg I am curious about your anti-pattern comment though; The resolve requires an object to be returned but the promise chain doesn't actually return anything directly b/c it stores the return val back to the singleStorageFactory so it will be overwritten on state change due to the data size issue. The deferred wraps true value in an object to push through the resolve but if I was to remove the deferred, how would I signal to the resolve that my promise chain in setState1 is complete?

    – Josey
    Nov 20 '18 at 20:15











  • Read You're Missing the Point of Promises. As written your $q.deferreds will hang if the parent asychronous functions return rejected promises.

    – georgeawg
    Nov 20 '18 at 21:30
















4















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?










share|improve this question




















  • 1





    Use a LRU cache such as $cacheFactory.

    – georgeawg
    Nov 20 '18 at 18:35











  • BTW the facadeFactory.State[12] methods are deferred anti-patterns and there is no need to manufacture promises for resolver functions as they accept both promises and synchronous variable.

    – georgeawg
    Nov 20 '18 at 19:53











  • @georgeawg Thanks. I'm looking into the $cacheFactory but I'm not sure it will solve the problem at hand; will experiment more.

    – Josey
    Nov 20 '18 at 20:13











  • @georgeawg I am curious about your anti-pattern comment though; The resolve requires an object to be returned but the promise chain doesn't actually return anything directly b/c it stores the return val back to the singleStorageFactory so it will be overwritten on state change due to the data size issue. The deferred wraps true value in an object to push through the resolve but if I was to remove the deferred, how would I signal to the resolve that my promise chain in setState1 is complete?

    – Josey
    Nov 20 '18 at 20:15











  • Read You're Missing the Point of Promises. As written your $q.deferreds will hang if the parent asychronous functions return rejected promises.

    – georgeawg
    Nov 20 '18 at 21:30














4












4








4








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?










share|improve this question
















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?







angularjs angular-ui-router






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 '18 at 20:29







Josey

















asked Nov 20 '18 at 16:21









JoseyJosey

181213




181213








  • 1





    Use a LRU cache such as $cacheFactory.

    – georgeawg
    Nov 20 '18 at 18:35











  • BTW the facadeFactory.State[12] methods are deferred anti-patterns and there is no need to manufacture promises for resolver functions as they accept both promises and synchronous variable.

    – georgeawg
    Nov 20 '18 at 19:53











  • @georgeawg Thanks. I'm looking into the $cacheFactory but I'm not sure it will solve the problem at hand; will experiment more.

    – Josey
    Nov 20 '18 at 20:13











  • @georgeawg I am curious about your anti-pattern comment though; The resolve requires an object to be returned but the promise chain doesn't actually return anything directly b/c it stores the return val back to the singleStorageFactory so it will be overwritten on state change due to the data size issue. The deferred wraps true value in an object to push through the resolve but if I was to remove the deferred, how would I signal to the resolve that my promise chain in setState1 is complete?

    – Josey
    Nov 20 '18 at 20:15











  • Read You're Missing the Point of Promises. As written your $q.deferreds will hang if the parent asychronous functions return rejected promises.

    – georgeawg
    Nov 20 '18 at 21:30














  • 1





    Use a LRU cache such as $cacheFactory.

    – georgeawg
    Nov 20 '18 at 18:35











  • BTW the facadeFactory.State[12] methods are deferred anti-patterns and there is no need to manufacture promises for resolver functions as they accept both promises and synchronous variable.

    – georgeawg
    Nov 20 '18 at 19:53











  • @georgeawg Thanks. I'm looking into the $cacheFactory but I'm not sure it will solve the problem at hand; will experiment more.

    – Josey
    Nov 20 '18 at 20:13











  • @georgeawg I am curious about your anti-pattern comment though; The resolve requires an object to be returned but the promise chain doesn't actually return anything directly b/c it stores the return val back to the singleStorageFactory so it will be overwritten on state change due to the data size issue. The deferred wraps true value in an object to push through the resolve but if I was to remove the deferred, how would I signal to the resolve that my promise chain in setState1 is complete?

    – Josey
    Nov 20 '18 at 20:15











  • Read You're Missing the Point of Promises. As written your $q.deferreds will hang if the parent asychronous functions return rejected promises.

    – georgeawg
    Nov 20 '18 at 21:30








1




1





Use a LRU cache such as $cacheFactory.

– georgeawg
Nov 20 '18 at 18:35





Use a LRU cache such as $cacheFactory.

– georgeawg
Nov 20 '18 at 18:35













BTW the facadeFactory.State[12] methods are deferred anti-patterns and there is no need to manufacture promises for resolver functions as they accept both promises and synchronous variable.

– georgeawg
Nov 20 '18 at 19:53





BTW the facadeFactory.State[12] methods are deferred anti-patterns and there is no need to manufacture promises for resolver functions as they accept both promises and synchronous variable.

– georgeawg
Nov 20 '18 at 19:53













@georgeawg Thanks. I'm looking into the $cacheFactory but I'm not sure it will solve the problem at hand; will experiment more.

– Josey
Nov 20 '18 at 20:13





@georgeawg Thanks. I'm looking into the $cacheFactory but I'm not sure it will solve the problem at hand; will experiment more.

– Josey
Nov 20 '18 at 20:13













@georgeawg I am curious about your anti-pattern comment though; The resolve requires an object to be returned but the promise chain doesn't actually return anything directly b/c it stores the return val back to the singleStorageFactory so it will be overwritten on state change due to the data size issue. The deferred wraps true value in an object to push through the resolve but if I was to remove the deferred, how would I signal to the resolve that my promise chain in setState1 is complete?

– Josey
Nov 20 '18 at 20:15





@georgeawg I am curious about your anti-pattern comment though; The resolve requires an object to be returned but the promise chain doesn't actually return anything directly b/c it stores the return val back to the singleStorageFactory so it will be overwritten on state change due to the data size issue. The deferred wraps true value in an object to push through the resolve but if I was to remove the deferred, how would I signal to the resolve that my promise chain in setState1 is complete?

– Josey
Nov 20 '18 at 20:15













Read You're Missing the Point of Promises. As written your $q.deferreds will hang if the parent asychronous functions return rejected promises.

– georgeawg
Nov 20 '18 at 21:30





Read You're Missing the Point of Promises. As written your $q.deferreds will hang if the parent asychronous functions return rejected promises.

– georgeawg
Nov 20 '18 at 21:30












1 Answer
1






active

oldest

votes


















0














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
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397261%2fbest-practice-for-clearing-factories-on-state-change-in-angularjs-1-x%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    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
    }





    share|improve this answer




























      0














      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
      }





      share|improve this answer


























        0












        0








        0







        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
        }





        share|improve this answer













        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
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 11 '18 at 13:32









        Tom EdwardsTom Edwards

        5810




        5810






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53397261%2fbest-practice-for-clearing-factories-on-state-change-in-angularjs-1-x%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith