I need the view to refetched the collection and re-render every 30 seconds. The problem is that once I change page (without a full page refresh) the setInterval stays on memory and keeps refetching in the background. However the view has long been destroyed.
Code:
define(
[
"underscore",
"collection/system/feed",
"view/list",
"text!template/index/system-feed.html"
],
function (_, Collection, ListView, Template) {
return ListView.extend({
el: '<div id="main-inner">',
collection: new Collection(),
loading: true,
client: false,
initialize: function (options) {
this.collection.fetch();
this.collection.on('reset', this.onFetchCollection, this);
var self = this;
setInterval(function() {
self.collection.fetch();
}, 30000);
},
/*collection is returned, so reset the loading symbol and set the posts to the render*/
onFetchCollection: function () {
this.list = this.collection.toJSON();
this.loading = false;
this.render();
},
render: function () {
var html = _.template(Template, {loading: this.loading, client: this.client, list: this.list});
this.$el.html(html);
return this;
}
});
}
);
I need the view to refetched the collection and re-render every 30 seconds. The problem is that once I change page (without a full page refresh) the setInterval stays on memory and keeps refetching in the background. However the view has long been destroyed.
Code:
define(
[
"underscore",
"collection/system/feed",
"view/list",
"text!template/index/system-feed.html"
],
function (_, Collection, ListView, Template) {
return ListView.extend({
el: '<div id="main-inner">',
collection: new Collection(),
loading: true,
client: false,
initialize: function (options) {
this.collection.fetch();
this.collection.on('reset', this.onFetchCollection, this);
var self = this;
setInterval(function() {
self.collection.fetch();
}, 30000);
},
/*collection is returned, so reset the loading symbol and set the posts to the render*/
onFetchCollection: function () {
this.list = this.collection.toJSON();
this.loading = false;
this.render();
},
render: function () {
var html = _.template(Template, {loading: this.loading, client: this.client, list: this.list});
this.$el.html(html);
return this;
}
});
}
);
Share
asked Aug 22, 2013 at 17:41
azz0razz0r
3,3117 gold badges47 silver badges85 bronze badges
3
-
Do you know when the view is "destroyed?" For example, if
remove()
is called on the view, you can override it and useclearInterval
to stop your recurring fetch. – Divey Commented Aug 22, 2013 at 17:51 - There are about 55 pages, so using clearInterval would be difficult, unless I used a standard name for intervals. I guess. – azz0r Commented Aug 22, 2013 at 17:52
-
But you really should be calling
view.remove()
every time you shut down a view (especially when you have 55 pages). Unless leaks are one of your application's features. Andcollection: new Collection()
doesn't do what you probably think it does. – mu is too short Commented Aug 22, 2013 at 17:55
3 Answers
Reset to default 9Assign a timer
variable to the setInterval and clear it out when you close the view.
initialize: function() {
this.timer = setInterval(function() {
self.collection.fetch();
}, 30000);
},
close: function() {
clearInterval(this.timer);
}
Or if you have a custom prototype method that is called when a view is closed, then just include it and the timer should be cleared out.
But make sure, you clean up the views before you move to the next page, which when not handled will cause memory leaks that would drastically slow down your application.
And it is always a better idea to attach the events to the views directly, instead of a model
or a collection
using listenTo
Replace
this.collection.on('reset', this.onFetchCollection, this);
with
this.listenTo(this.collection, 'reset', this.onFetchCollection);
This way if you remove the view, even the event bindings would be taken care off. Otherwise you would need to explicitly unbind the events on the collection.
Just calling this.stopListening()
would take care of unbinding all the events on the view.
You could use setTimeout instead. It could look something like this.
return ListView.extend({....
initialize: function() {
....
var self = this;
self.fetchCollection();
}
, fetchCollection: function() {
var self = this;
self.collection.fetch();
this.timeout = setTimeout(function() {
self.fetchCollection
}, 30000 );
}
, close: function() {
window.clearTimeout( this.timeout );
}
First you need to get a reference to your interval and save it so you can stop it later. setInterval returns an interval Id for this purpose
var self = this;
self.interval = setInterval(function() {
self.collection.fetch();
}, 30000);
Then when you want to stop it (I assume you would want to stop it on the undelegate events event because it sounds like you are hiding/reshowing the view)
undelegateEvents: function(){
clearInterval(this.interval);
}