最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Backbone: using setInterval - Stack Overflow

programmeradmin1浏览0评论

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 use clearInterval 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. And collection: new Collection() doesn't do what you probably think it does. – mu is too short Commented Aug 22, 2013 at 17:55
Add a ment  | 

3 Answers 3

Reset to default 9

Assign 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);
}
发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>