JavaScript的setInterval可以阻止线程执行吗?

时间:2012-08-15 23:03:22

标签: javascript google-chrome-extension xmlhttprequest gmail setinterval

setInterval结果可以阻止页面中的其他脚本吗?

我正在开展一个项目,将与Gmail相关的书签转换为Google Chrome扩展程序。 bookmarklet使用gmail greasemonkey API与gmail页面进行交互。 API的JavaScript对象是要加载的Gmail页面的最后部分之一,并通过XMLHttpRequest加载到页面中。由于我需要访问此对象,并且从扩展内容脚本中隐藏了全局JavaScript变量,因此我将一个脚本注入gmail页面,该页面轮询变量的定义然后访问它。我正在使用setInterval函数进行轮询。这大约有80%的时间都有效。其余的时间轮询功能一直保持轮询,直到达到我设置的限制,并且页面中永远不会定义greasemonkey API对象。

注入脚本示例:

    var attemptCount = 0;

    var attemptLoad = function(callback) {

        if (typeof(gmonkey) != "undefined"){
            clearInterval(intervalId);  // unregister this function for interval execution.
            gmonkey.load('1.0', function (gmail) {
                self.gmail = gmail;
                if (callback) { callback(); }
            });
        }
        else {
            attemptCount ++;  
            console.log("Gmonkey not yet loaded: " + attemptCount );
            if (attemptCount > 30) {
                console.log("Could not fing Gmonkey in the gmail page after thirty seconds.  Aborting");
                clearInterval(intervalId);  // unregister this function for interval execution.
            };
        }
    };

    var intervalId = setInterval(function(){attemptLoad(callback);}, 1000);

2 个答案:

答案 0 :(得分:10)

Javascript是单线程的(除了我们在这里没有讨论的网络工作者)。这意味着只要正常的javascript执行线程正在运行,你的setInterval()计时器就不会运行,直到执行的常规javascript线程完成。

同样,如果您的setInterval()处理程序正在执行,则在您的setInterval()处理程序完成执行当前调用之前,不会触发其他javascript事件处理程序。

因此,只要您的setInterval()处理程序不会卡住并永远运行,它就不会阻止其他事情最终运行。它可能会略微延迟它们,但它们仍会在当前setInterval()线程完成后立即运行。

在内部,javascript引擎使用队列。当某些东西想要运行时(比如事件处理程序或setInterval()回调)并且某些东西已经运行,它会将一个事件插入到队列中。当前的javascript线程完成执行时,JS引擎会检查事件队列,如果有什么东西,它会在那里选择最旧的事件并调用它的事件处理程序。

以下是关于Javascript事件系统如何工作的一些其他参考:

How does JavaScript handle AJAX responses in the background?

Are calls to Javascript methods thread-safe or synchronized?

Do I need to be concerned with race conditions with asynchronous Javascript?

答案 1 :(得分:4)

setInterval和setTimeout是"礼貌",因为当你认为他们愿意时他们不会开火 - 他们会在线程清晰时触发, 之后你指定的点。

因此,安排某些事情的行为不会阻止其他东西运行 - 它只是将自己设置为在当前队列的末尾运行,或者在指定时间结束时运行(以较长者为准)

两个重要的警告:

第一个是setTimeout / setInterval具有特定于浏览器的最小值。他们经常在15ms左右。因此,如果您每1ms请求一次,浏览器实际上会将它们安排为每个browser_min_ms(不是真正的变量)。

第二个是使用setInterval,如果回调中的脚本比间隔长,那么你可以遇到一个火车残骸,浏览器会在这里排队积压间隔。

function doExpensiveOperation () {
    var i = 0, l = 20000000;
    for (; i < l; i++) {
        doDOMStuffTheWrongWay(i);
    }
}


setInterval(doExpensiveOperation, 10);

这个邮件+ = 1;

但是对于您的代码而言,与您正在做的事情一样, 。 就像我说的那样,setInterval不会中止其他任何事情发生,它只是将自己注入下一个可用的插槽。

我可能会建议你使用setTimeout作为通用的东西,但是你仍然可以很好地保持间隔并保持间隔。

代码中的其他地方可能还有其他内容 - 无论是在Google的投放中还是在您的收藏中。