Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用setTimeout绕过IE脚本警告_Javascript_Internet Explorer_Settimeout_Setinterval - Fatal编程技术网

Javascript 使用setTimeout绕过IE脚本警告

Javascript 使用setTimeout绕过IE脚本警告,javascript,internet-explorer,settimeout,setinterval,Javascript,Internet Explorer,Settimeout,Setinterval,我正在尝试编写一个web应用程序,它使用Javascript执行相当复杂的计算(包括阶乘和贝塞尔函数)。当我在IE中运行脚本时,它会警告我脚本没有响应或需要很长时间,并询问我是否要继续运行它。我已经读到,为了解决这个问题,您可以使用setTimeout或setInterval命令从本质上重置IE用于确定脚本是否长期运行的计数器 我尝试过实现这一点,但没有成功。当我运行探查器时,我的计算阶乘的函数似乎占用了大部分时间,所以我想在该函数中使用setTimeout。以下是我目前拥有的功能: funct

我正在尝试编写一个web应用程序,它使用Javascript执行相当复杂的计算(包括阶乘和贝塞尔函数)。当我在IE中运行脚本时,它会警告我脚本没有响应或需要很长时间,并询问我是否要继续运行它。我已经读到,为了解决这个问题,您可以使用setTimeout或setInterval命令从本质上重置IE用于确定脚本是否长期运行的计数器

我尝试过实现这一点,但没有成功。当我运行探查器时,我的计算阶乘的函数似乎占用了大部分时间,所以我想在该函数中使用setTimeout。以下是我目前拥有的功能:

function factorial(x) {
    var buff = 1;

    for (i=x;i>=1;i--) {
        buff = buff * i;
    }

    return buff
}
我尝试过用类似这样的代码替换代码,但无法正常工作:

function factorial(x) {
    if (x==0) {
        factbuff=1;
    }
    else {
        factbuff = x;
        factidx = x;
        setTimeout('dofact()',50);
    }
    return factbuff
}

function dofact() {
    if (factidx > 1) {
        factidx--;
        factbuff = factbuff * factidx;
    }
}

任何人都知道我做错了什么,以及我如何正确实现setTimeout函数,以便在消除IE中的脚本警告的同时计算阶乘?

这是一个更新,并解释了为什么先前答案中的代码(现在已删除)是错误的

首先,让我们重申这个问题:允许阶乘函数在IE中运行,而不需要 触发“长时间运行脚本”警告

这是以前提出的准则:

BROKEN. DO NOT USE. 

var executions = 0;
function factorial(x) {
    executions++;
    if (x > 1) {
    if (executions % 100 === 0) {
    return (function() {  // NO NO NO
        var y = x;
        setTimeout(function(y) { return y*factorial(y-1); }, 50);
    })();
    } else {
        return x*factorial(x-1);
    }
    } else {
    return 1;
    }
}
好的,那么代码有什么问题

  • 阶乘函数本身是递归的。这意味着函数会调用自身。每次函数调用自身时,内存中都会出现另一个堆栈帧。上面的代码试图做的是调用自己一百次。我不知道浏览器可以容纳多少嵌套堆栈帧,但100似乎有点高。我会分10批做

  • 上面提出的函数不是异步的。当您使用setTimeout()绕过IE警告时,函数需要变为异步。这意味着-而不是像
    var value=func(x)那样调用它,则需要转换代码以传递回调,异步函数在得到结果时调用回调

  • 与上述问题相关,在建议的代码中使用setTimeout是错误的。在一个地方,代码执行以下操作:

    return (function() {  // NO NO NO
        var y = x;
        setTimeout(function(y) { return y*factorial(y-1); }, 50);
    })();
    
  • 那有什么用?让我们把它分解一下。它有一个匿名函数。该函数被调用(由末尾的open-close参数调用)。调用的值由主阶乘函数返回。调用anon函数的价值是什么?问题a:它不返回值。它是未定义的。(见附件)

    修复它并不像将调用的值返回到
    setTimeout()
    那么简单。这也是错误的。它肯定不是setTimeout调用的值


    好的,怎么修?首先,认识到阶乘函数是异步的,因此获取和显示结果如下:

    function displayFacResult(result) {
        var t2 = document.getElementById('t2');
        t2.value = result;
    }
    
    function b1_Click() {
        var t1 = document.getElementById('t1'),
            value = parseInt(t1.value, 10);
        computeFactorialAsynchronously(value, displayFacResult);
    }
    
    单击按钮调用“compute”,并向其传递调用结果的函数的名称。使用结果调用的函数实际上执行显示。这是异步调用模式

    好,现在开始计算

    function computeFactorialAsynchronously(firstX, callback) {
        var batchSize = 3, limit=0, result = 1;
        var doOneFactorialStep = function(x, steps) {
            if (steps) { limit = x - steps; }
            if (x==1) { callback(result); }
            if (x>limit) {
                result *= x;
                doOneFactorialStep(x-1);
            }
            else {
                setTimeout(function () {
                    doOneFactorialStep(x, batchSize);
                }, 1);
            }
        };
        doOneFactorialStep(firstX, batchSize);
    
        // the actual return value of the computation
        // always comes in the callback.
        return null;
    }
    
    它通过“chunk”计算阶乘,每个chunk涉及N次乘法,并由上面的变量“steps”表示。N(步长)的值决定递归的级别。100可能太大了。3可能太小,无法获得良好的性能,但它说明了异步性

    在computeFactorialAsynchronously函数中,有一个helper函数,它计算一个块,然后调用setTimeout来计算下一个块。有一些简单的算法可以管理何时停止计算当前块

    工作示例:


    从某种意义上讲,转移到异步模型将使您远离纯粹的函数隐喻,即计算的结果就是函数的结果。我们可以在javascript中实现这一点,但它会出现IE“long running script”警告。为了避免警告,我们使用异步,这意味着“ComputeFactory”的返回值不是实际的阶乘。在异步模型中,我们通过一个“副作用”得到结果,即计算函数在完成计算时调用的回调函数

    看看这本很棒的教程,若你们把factorial重写成递归的,然后在n-1上为mod 10调用factorial之前加上一个setTimeout呢?这就是问题所在。我不太清楚setTimeout是如何工作的。您是建议我将setTimeout命令放在factorial()函数本身中,还是放在另一个调用factorial()的函数中?