Javascript 等到回调中触发的最后一个事件再继续

Javascript wait until last event fired in callback before proceeding

这几乎是一个基本的 Javascript 问题,尽管它涉及一些 Chrome 扩展 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);
    }
});

我想我的脚本现在所做的就是延迟一切。我想让它做的是每次出现 'complete' 状态时,我想检查 5 秒,然后记录 'here'。如果另一个 'complete' 触发,我想摆脱以前的计时器并启动一个新计时器。基本上等到所有 'complete' 都被解雇...我需要帮助修复我的间隔逻辑...

您必须在函数作用域外声明您的 timerinterval,否则它将在该作用域内声明一个新的,并且您的 clearInterval 无法清除之前的间隔回调。

编辑:感谢 stdob--,现在更改了外部变量以坚持 eventTarget,因此不再需要在注册事件之前声明 variables

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

所以现在每个 intervaltimer 都指向同一个目标。

或者如果你不关心每一秒发生的事情,为什么不使用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);
    }
});