如何在递归中使用setTimeout以避免浏览器卡在复杂的进程上

时间:2013-02-25 18:15:01

标签: javascript recursion cpu-usage single-threaded

我有这个代码使用消耗大量内存的inefficientProcess()

我的目标是使用某种setTimeout(function(){...},0)技术,以便浏览器在执行代码时不会卡住。

如何更改代码以使其适用于setTimeout?

function powerOfTwo(num) {
    inefficientProcess();
    if (num > 0) {
        return powerOfTwo(num-1)*2;
    } else {
        return 1;
    }
}

function inefficientProcess() {
    var sum;
    for (var i=0; i < 500000; i++) {
        sum+=10;
    }
}

powerOfTwo(1000);

我的目标是学习如何在执行大量计算时避免浏览器崩溃。

3 个答案:

答案 0 :(得分:3)

Javascript是单线程的,您的所有代码都是阻止的。 HTML5中有一个新标准WebWorkers API,它允许您将任务委派给不同的线程。然后,您可以传递一个回调函数来执行结果。

https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers

简单示例:

function powerOfTwo(num, callback) {
    var worker = new Worker('inneficient.js');
    worker.postMessage('runTask');
    worker.onmessage = function(event) {
        var num = event.data.result;
        var pow;
        if (num > 0) {
            pow = Multiply(num-1)*2;
        } else {
            pow = 1;
        }
        callback(pow);
    };    
}

powerOfTwo(1000, function(pow){
    console.log('the final result is ' + pow);
});
在inneficient.js中你有类似的东西:

// inneficient.js

function inefficientProcess() {
    var sum;
    for (var i=0; i < 500000; i++) {
        sum+=10;
    }
     postMessage({ "result": sum});
}

inefficientProcess();

答案 1 :(得分:2)

正如Andre的回答中所提到的,有一个新的HTML5标准,允许您在不同的线程上启动任务。否则,您可以调用setTimeout,时间为0,以便在调用inefficientProcess之前完成当前执行路径(可能还有一些UI更改要呈现)。

但是你是否可以使用HTML5,必须将powerOfTwo函数更改为异步 - 无论谁调用它都需要提供一个回调方法,当(a)通过WebWorkers返回的线程返回时,将调用该方法,或者( b)setTimeout方法完成。

编辑添加示例:

function powerOfTwo(num, callback)
{
    setTimeout(function ()
    {
        inefficientProcess();
        if (num > 0)
            callback(Multiply(num-1)*2);
        else
            callback(1);
    }, 0);
}

function inefficientProcess() { ... }

答案 2 :(得分:0)

  

HTML元素允许您定义JavaScript的时间   页面中的代码应该开始执行。 “异步”和“推迟”   属性在9月初被添加到WebKit。 Firefox一直都是   已经支持他们很久了。

Site

上看到了