如何避免 JavaScript CallStack 过载?

发布于 2024-12-05 14:11:49 字数 870 浏览 0 评论 0原文

下面的 javascript 完成以下任务(这是针对 Node.js COMET 应用程序):

  1. 向服务器发出请求并保留,直到服务器有需要处理的内容为止 返回。
  2. 一旦请求返回,数据就会被处理,然后另一个 请求立即在回调函数中发出 成功事件。
  3. 如果发生超时(服务器在时间范围内没有返回任何内容) 在错误事件的回调函数中发出另一个请求。

我担心(我认为这是有效的)是请求不断添加到调用堆栈中,就像永无止境的递归函数一样。一段时间后,它会导致浏览器最终崩溃并变得无响应(至少我认为这是原因)。

我怎样才能完成同样的事情并避免这个问题?

function GetData(){
    $.ajax({
        url: "admin.html",
        type: "POST",
        dataType: "json",
        contentType: 'text/json',
        data: JSON.stringify({
            cmd: "getData"
        }),
        timeout: (60 * 1000),
        success: function(data, textStatus, jqXHR){
            UpdateScreen(data);
            GetData();
        },
        error: function(jqXHR, textStatus, errorThrown){
            if(textStatus == "timeout"){
                GetData();
            }
        }
    });
}

The javascript below accomplishes the following (this is for a node.js COMET application):

  1. Request is made to the server and held until the server has something to
    return.
  2. Once the request returns the data is processed and another
    request is immediately made within the callback function of the
    success event.
  3. If a timeout occurs (the server had nothing to return within the time frame)
    another request is made within the callback function of the error event.

My concern (which I believe is valid) is that the requests are continually added to the callstack, much like a recursive function that never ends. After a while, it results in the browser eventually crashing and becoming unresponsive (at least I think this is the cause).

How can I accomplish the same thing and avoid this problem?

function GetData(){
    $.ajax({
        url: "admin.html",
        type: "POST",
        dataType: "json",
        contentType: 'text/json',
        data: JSON.stringify({
            cmd: "getData"
        }),
        timeout: (60 * 1000),
        success: function(data, textStatus, jqXHR){
            UpdateScreen(data);
            GetData();
        },
        error: function(jqXHR, textStatus, errorThrown){
            if(textStatus == "timeout"){
                GetData();
            }
        }
    });
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤独陪着我 2024-12-12 14:11:49

不,我很确定你没事。 ajax 事件是异步的,因此 GetData 函数将完成,浏览器将等待事件,然后再从成功处理程序中再次调用 GetData

可以将其视为 GetData 函数,它只是定义要执行的操作,而不是实际执行操作。然后它完成执行(并清除堆栈)并且浏览器执行这些操作。

No, I'm pretty sure you are OK. The ajax event is asynchronous, so the GetData function will finish and the browser will wait for events, before it calls GetData again from the success handler.

Think of it as the GetData function just defining what to do, not actually doing it. Then it finishes executing (and clears the stack) and browser does those actions.

若水微香 2024-12-12 14:11:49
function GetData(limit){
    limit = limit || 0;
    $.ajax({
        url: "admin.html",
        type: "POST",
        dataType: "json",
        contentType: 'text/json',
        data: JSON.stringify({
            cmd: "getData"
        }),
        timeout: (60 * 1000),
        success: function(data, textStatus, jqXHR){
            UpdateScreen(data);
            GetData();
        },
        error: function(jqXHR, textStatus, errorThrown){
            if(textStatus === "timeout" && limit < 20){
                GetData(++limit); 
            } else {
                //throw "epic fail"
                setTimeout(GetData, 0);
            }
        }
    });
}

只需添加一点超时限制计数器即可。如果它变得太大,要么放弃并抛出错误,要么通过调用异步的 setTimeout 来中断调用堆栈。

function GetData(limit){
    limit = limit || 0;
    $.ajax({
        url: "admin.html",
        type: "POST",
        dataType: "json",
        contentType: 'text/json',
        data: JSON.stringify({
            cmd: "getData"
        }),
        timeout: (60 * 1000),
        success: function(data, textStatus, jqXHR){
            UpdateScreen(data);
            GetData();
        },
        error: function(jqXHR, textStatus, errorThrown){
            if(textStatus === "timeout" && limit < 20){
                GetData(++limit); 
            } else {
                //throw "epic fail"
                setTimeout(GetData, 0);
            }
        }
    });
}

Just add a little timeout limit counter. if it gets too big either give up and throw an error or break the call stack by calling setTimeout which is asynchronous.

递刀给你 2024-12-12 14:11:49

我想知道您的 UpdateScreen(data) 方法是否有问题。这也是一个递归函数吗?人们建议您简单地使该方法超时并不能真正解决问题,它只是中止该过程。我会尝试分别在成功和错误回调中记录类似 console.log("get data success") 和 console.log("get data error") 的内容。如果您的日志页充满了一条消息,您就知道在哪里不断调用 GetData() 方法。它可能总是超时。

顺便说一句,您应该将错误的 if 语句更改为类似的内容,

   if(jqxhr.responseText == "timeout"){
      getData();
   }

请参阅此处以了解原因: jQuery Ajax 错误处理,显示自定义异常消息

I'm wondering if your UpdateScreen(data) method is the problem. Is that a recursive function as well? People suggesting that you simply timeout the method doesn't actually fix the problem, it simply aborts the process. I would try logging something like console.log("get data success") and console.log("get data error") in your success and error callbacks respectively. If your log page is full of one message, you know where the GetData() method is continually called. It could be always timing out.

On a side note, you should change your if statement for an error to something like

   if(jqxhr.responseText == "timeout"){
      getData();
   }

see here for explanation why: jQuery Ajax error handling, show custom exception messages

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文