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

B S*_*arp 1 javascript gmail xmlhttprequest setinterval google-chrome-extension

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);
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 10

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

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

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

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

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

JavaScript如何在后台处理AJAX响应?

调用Javascript方法是线程安全的还是同步的?

我是否需要关注异步Javascript的竞争条件?


Nor*_*ard 5

setInterval 和 setTimeout 是“礼貌的”,因为它们不会在您认为它们会触发时触发——您指定的点之后,只要线程空闲,它们就会触发。

因此,调度某些内容的行为不会阻止其他内容的运行——它只是将自身设置为在当前队列的末尾或指定时间的末尾(以较长者为准)运行。

两个重要的警告:

第一个是 setTimeout/setInterval 具有特定于浏览器的最小值。通常,它们约为 15 毫秒。因此,如果您每 1 毫秒请求一些内容,浏览器实际上会将它们安排为每隔 browser_min_ms (不是真正的变量)。

第二个是,使用 setInterval 时,如果回调中的脚本花费的时间比间隔长,您可能会陷入困境,浏览器将继续排队积压间隔。

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


setInterval(doExpensiveOperation, 10);
Run Code Online (Sandbox Code Playgroud)

坏时光+=1;

但具体而言,对于您的代码来说,您所做的事情并没有本质上的错误。就像我说的,setInterval 不会中止任何其他事情的发生,它只会将自己注入到下一个可用的插槽中。

我可能会建议您使用 setTimeout 来实现通用目的,但您仍然可以很好地保持时间间隔并保持间隔。

代码中的其他地方可能还发生了其他事情——无论是在 Google 的交付中,还是在您的集合中。


归档时间:

查看次数:

5683 次

最近记录:

9 年,5 月 前