为什么javascript函数可以在firefox中使用,而不能在Chrome或IE上使用

为什么javascript函数可以在firefox中使用,而不能在Chrome或IE上使用,javascript,jquery,internet-explorer,google-chrome,cross-browser,Javascript,Jquery,Internet Explorer,Google Chrome,Cross Browser,我创建了一个启动活动指示器的方法,以及一个停止给定指示器的不同方法。然后,当执行耗时的任务时,我在前面调用start方法,在后面调用stop方法。调用的示例如下所示: // Show loading viewControllerShowAjax(); // Tasks that take time including large calculations and ajax requests app.timeConsumingFunction(); // Hide loading vie

我创建了一个启动活动指示器的方法,以及一个停止给定指示器的不同方法。然后,当执行耗时的任务时,我在前面调用start方法,在后面调用stop方法。调用的示例如下所示:

// Show loading
viewControllerShowAjax();

// Tasks that take time including large calculations and ajax requests   
app.timeConsumingFunction();

// Hide loading
viewControllerHideAjax();
这是在firefox上工作,但在IE或Chrome上都不工作。有解决办法吗

编辑: 以下是我正在使用的功能:

function viewControllerInit() {
    // Other initializations
    ...

    // Initializing the activity indicator; the activity indicator is simply a jqueryui modal view with a spinjs spinner in it.
    $(this.ajaxModalSelector).dialog({
        resizable   : false,
    dialogClass : "no-close ajax",
    autoOpen    : false,
    height      : 500,
    width       : 500,
    modal       : true,
    open: function( event, ui ) {
        $(this.ajaxModalSelector).dialog("open");
            var opts = {
              lines: 12,
              length: 0,
              width: 20,
              radius: 40,
              color: '#000',
              speed: 1.3,
              trail: 50,
              shadow: false,
            };
            this.spinner = new Spinner(opts).spin(document.getElementById("ajax-modal"));
        },
        beforeClose: function( event, ui ) {
            this.spinner.stop();
        }
    });
}
// Opens the jquery ui modal view
function viewControllerShowAjax() {
    $(this.ajaxModalSelector).dialog("open");
}
// Closes the jquery ui modal view
function viewControllerHideAjax() {
    $(this.ajaxModalSelector).dialog("close");
}
编辑:了解有关问题的更多信息;我发现,如果没有为活动指示器调用hide函数,那么它将在耗时的任务完成后出现。同样,这是IE和Chrome中的行为,但不是firefox。

可能的原因 这不起作用的原因是JavaScript是单线程的

耗时的函数
app.timeConsumingFunction()
将阻止用户界面在Chrome和IE中更新

它在Firefox中工作的原因很简单,因为FF有一个不同的实现,可以说它允许UI事件在两者之间执行(Canary和我相信Chrome也有一个实验模式,允许UI更新在单独的线程上执行)

浏览器通常会提示不同的事件,例如绘制事件。然后遍历此队列并逐个事件执行

但是,例如,如果队列条目正在执行耗时函数的上下文,则该队列将没有“喘息空间”继续处理该队列中的其他事件

这将是执行绘制事件的一部分,否则将绘制微调器。由于它被阻止,在耗时的函数完成之前,微调器不会出现

使用setTimeout的可能解决方案 解决此问题的方法是使用
setTimeout
或a(参见下面的Web Worker示例)来分割执行

你可以尝试这样来看看它是否改进了当前代码(虽然我很怀疑,但是它很简单,值得一试)-因为在这个帖子中没有足够的代码来测试这个,请考虑它的理论。尝试替换此行:

app.timeConsumingFunction();

如果这还不够,您将需要进行类似的设置,但需要使用函数的内部(您没有显示),如果可能的话,您可以将其划分为处理不同操作阶段的部分。一个基本示例可以是:

app.timeConsumingFunction = function() {

    var hereIsAvailableToAllParts;

    function part1() {
        // step 1 in time-consuming operation
        setTimout(part2, 0);  //start next part
    }

    function part2() {
        // step 2 in time-consuming operation
        setTimout(part3, 0);
    }

    function part3() {
        // step 3 in time-consuming operation
        ...done or next...
    }
    setTimeout(part1, 0);
}
setTimeout
的0参数告诉浏览器在第一时间将此事件排队。这可能并不总是有效的,但您可以使用大约11毫秒的间隔,这接近最小可用队列片

通过拆分这样的操作,您将允许浏览器执行例如介于两者之间的绘制事件,从而能够看到微调器

使用Web Workers的可能解决方案 在不了解您的代码的情况下,我不能说Web Workers在这种情况下是可用的,因为有一些限制,例如没有DOM访问、没有存储访问等。但是,这种方法非常好,如果您的代码可能的话,我会推荐这种方法(参考限制)

<>但是如果你做纯粹的计算,认为网络工作者是一种选择:

一个简单的例子:

在主脚本中,您可以按如下方式分配Web Worker:

var ww = new Worker(urlToWebWorkerScriptHere);
网络工作者通过信息进行交流,因此在“我们”这一方,我们会收听
信息
事件:

ww.onmessage = function (e) {

    var msg = e.data;

    /// message returned can be anything you like (see next section)
    if (msg === 'Done!') viewControllerHideAjax();
};
Web Worker使用一个单独的脚本,该脚本可以作为单独的JS文件加载,也可以使用一些技巧将其与HTML代码内联(如下图所示)

脚本是在一个独立的上下文中执行的,并且是进行所有计算的地方。完成后,它将显示我们的主脚本:

onmessage = function(e) {

    /// you can send any commands you want and call them what you want
    /// for example, I have called the command start

    if (e.data === 'start') {

        /// the time consuming stuff..

        /// when finished, send 'Done!' to main script
        postMessage('Done!');
    }
};
要开始计算,请执行以下操作:

// Show loading
viewControllerShowAjax();

// Tasks that take time including large calculations and ajax requests   
ww.postMessage('start');
(当从worker返回“Done!”消息时调用hide)

当然,您可以来回发送许多消息,例如返回部分结果并触发下一部分计算(或操作)

我在下面的fiddle中做了一个简单的演示-请注意,即使fiddle中的循环正在进行繁忙的循环/繁重的工作,您也可以单击右键(在示例中,您还可以看到如何内联Web Worker脚本,而不是单独加载它):

但是,同样,如果没有看到您的工作代码,我无法判断是否可以使用Web Workers

在任何情况下,这都应该为如何解决这一问题提供一些指导。

可能的原因 这不起作用的原因是JavaScript是单线程的

耗时的函数
app.timeConsumingFunction()
将阻止用户界面在Chrome和IE中更新

它在Firefox中工作的原因很简单,因为FF有一个不同的实现,可以说它允许UI事件在两者之间执行(Canary和我相信Chrome也有一个实验模式,允许UI更新在单独的线程上执行)

浏览器通常会提示不同的事件,例如绘制事件。然后遍历此队列并逐个事件执行

但是,例如,如果队列条目正在执行耗时函数的上下文,则该队列将没有“喘息空间”继续处理该队列中的其他事件

这将是执行绘制事件的一部分,否则将绘制微调器。由于它被阻止,在耗时的函数完成之前,微调器不会出现

使用setTimeout的可能解决方案 解决此问题的方法是使用
setTimeout
或a(参见下面的Web Worker示例)来分割执行

你可以尝试这样来看看它是否改进了当前代码(虽然我很怀疑,但是它很简单,值得一试)-因为在这个帖子中没有足够的代码来测试这个,请考虑它的理论。尝试

// Show loading
viewControllerShowAjax();

// Tasks that take time including large calculations and ajax requests   
ww.postMessage('start');