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?
angularjs angular-ui-router
add a comment |
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
1
Use a LRU cache such as $cacheFactory.
– georgeawg
Nov 20 '18 at 18:35
BTW thefacadeFactory.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.deferred
s will hang if the parent asychronous functions return rejected promises.
– georgeawg
Nov 20 '18 at 21:30
add a comment |
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
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
angularjs angular-ui-router
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 thefacadeFactory.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.deferred
s will hang if the parent asychronous functions return rejected promises.
– georgeawg
Nov 20 '18 at 21:30
add a comment |
1
Use a LRU cache such as $cacheFactory.
– georgeawg
Nov 20 '18 at 18:35
BTW thefacadeFactory.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.deferred
s 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.deferred
s 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.deferred
s will hang if the parent asychronous functions return rejected promises.– georgeawg
Nov 20 '18 at 21:30
add a comment |
1 Answer
1
active
oldest
votes
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
}
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
}
add a comment |
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
}
add a comment |
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
}
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
}
answered Dec 11 '18 at 13:32


Tom EdwardsTom Edwards
5810
5810
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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.deferred
s will hang if the parent asychronous functions return rejected promises.– georgeawg
Nov 20 '18 at 21:30