denikov
denikov

Reputation: 869

Javascript wait until last event fired in callback before proceeding

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...

Upvotes: 0

Views: 659

Answers (1)

fuyushimoya
fuyushimoya

Reputation: 9813

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);
    }
});

Upvotes: 2

Related Questions