如何在JavaScript中编写递归阻塞函数而不会溢出堆栈

How do I write a recursive blocking function in JavaScript without overflowing the stack?

本文关键字:函数 堆栈 溢出 递归 JavaScript      更新时间:2023-09-26

感谢您的关注。

<标题> 的背景

我正在为客户端编写一个javascript繁重的应用程序,并且需要一个实用程序函数,我可以通过一个条件和一个回调函数。如果不满足条件,我需要等待几毫秒,然后再次测试。如果满足条件,则执行回调。

目前我有什么

我已经将这个方法作为实用程序类的一部分编写:

 ThreadLocker: function (condition, callback) {
        //If condition is true then it resumes running code
        if (condition()) {
            callback();
        } else { //Else it waits 10ms and tries again
            setTimeout(Util.ThreadLocker(condition,callback), 10);
        }
    }

下面是它的用法:

   var condition = function(){return (myGlobalVariable == "foo") ? true : false;};
   var callback = function(){alert("Ready to rock!");};
    Util.Threadlocker(condition,callback);
<标题>

即使我将超时时间设置为10 ,我也会立即获得堆栈溢出。这是Chrome给我的:

"超过最大调用堆栈大小。"

如果你看一下堆栈,看起来这个函数在一毫秒或两毫秒内被调用了几十次,即使setTimeOut被设置为10秒。

我在这里做错了什么?

setTimeout(Util.ThreadLocker(condition,callback), 10);

直接调用你的'ThreadLocker'函数,没有超时设置。试着

setTimeout(function () { Util.ThreadLocker(condition,callback); }, 10);

你可能还需要知道,javaScript不是多线程的。它只是在n毫秒后调度函数,或者在没有其他任务执行时立即调度函数。对于间隔也是一样,如果您创建一个10ms的间隔:任务需要30ms,它将在第10ms执行,然后在第40 ms开始执行(在第一个任务完成后立即执行)。

所以你不能真正锁,但也没有其他东西可以竞争你的代码。

至于堆栈溢出:如果你真的有这种情况,例如:一个递归函数可能会溢出500万行的堆栈(在IE中,在页面加载期间执行的Javascript行数),您可以使用超时0来延迟函数:

setTimeout(function () { }, 0);