0

This is pretty much a basic Javascript question even though it involves some Chrome Extension API.

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
        //complete may fire multiple times per page update
        var timer = 0, interval;
        console.log(changeInfo.status);
        clearInterval(interval);
        interval = setInterval(function() {
            if (timer == 5) {
                console.log('here');
                clearInterval(interval);
            }
            timer++;
        }, 1000);
    }
});

I think all my script does right now is delay everything. What I want it to do is every time a 'complete' status happens, I want to check for 5 seconds to go by and then log 'here'. If another 'complete' fires, I want to get rid of the previous timer and start a new one. Basically wait until all 'complete's are fired...I need help fixing my interval logic...

denikov
  • 877
  • 2
  • 17
  • 35

1 Answers1

2

You have to declare your timer, and interval outside the function scope, or it'll declare a new one in that scope, and your clearInterval can't clear previous interval callback.

Edit: Thanks to stdob--, now changed the variable outside to stick to the eventTarget, so no need to declare variables before register event anymore.

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
        //complete may fire multiple times per page update
        console.log(changeInfo.status);
        // Clear prev counter, if exist.
        if (this.interval != null) {
            clearInterval(this.interval);
        }
        // init timer
        this.timer = 0;                
        this.interval = setInterval(function() {
            if (this.timer == 5) {
                console.log('here');
                clearInterval(this.interval);
                this.interval = null;
            }
            this.timer++;
        }.bind(this), 1000);  // Important to .bind(this) so that context will remain consistent.
    }
});

So now every interval and timer points to the same target.

Or if you doesn't care about what happens in every second, why not use setTimeout:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
        console.log(changeInfo.status);
        if (this.timeout != null) {
            clearTimeout(this.timeout);
        }

        this.timeout = setTimeout(function() {
            console.log("here");
            this.timeout = null;
        }.bind(this), 5000);
    }
});
Community
  • 1
  • 1
fuyushimoya
  • 9,715
  • 3
  • 27
  • 34
  • 1
    Best way use static variable: this.interval = setInterval(...) – stdob-- Jul 05 '15 at 18:41
  • @stdob but then if he use the setInterval way, he needs to bind the interval callback to `this`, right? – fuyushimoya Jul 05 '15 at 18:47
  • Why not if he not want access to interval outise? Some like this: `if (typeof this.interval == 'undefined') this.interval = null;` @fuyushimoya – stdob-- Jul 05 '15 at 18:51
  • @stdob-- yep, I take a cheat here use `if (this.interval != null)` to check if it exist, take a look to check if I made some mistake? – fuyushimoya Jul 05 '15 at 18:53
  • It would be more accurate to check by `typeof` if variable is declared or not. And can be set to `null`: `clearInterval` fully accepts null as input. @fuyushimoya – stdob-- Jul 05 '15 at 18:58
  • @stdob-- I get that from [How to check for an undefined or null variable in JavaScript?](http://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript), and [jquery-Equality](http://contribute.jquery.org/style-guide/js/#equality), so I think `this.interval != null` should be enough? – fuyushimoya Jul 05 '15 at 19:03
  • Of course - it's work. But this conceptual question - what if you want to assign a value different from `null` in the first function call? )) @fuyushimoya – stdob-- Jul 05 '15 at 19:07
  • To be quite boring, the best option would be: `if (!this.hasOwnProperty("interval")) this.interval = null;` @fuyushimoya – stdob-- Jul 05 '15 at 19:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82424/discussion-between-fuyushimoya-and-stdob). – fuyushimoya Jul 05 '15 at 19:18