【问题标题】:How can I avoid overloading the JavaScript CallStack?如何避免 JavaScript 调用堆栈重载?
【发布时间】:2011-09-22 08:24:00
【问题描述】:

下面的 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();
            }
        }
    });
}

【问题讨论】:

  • 你签出socket.io了吗?可能对您的情况有用。
  • 不应该是textStatus == "timeout"吗?
  • @jdigital - 不错不错!

标签: javascript jquery node.js comet


【解决方案1】:

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

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

【讨论】:

  • 对了,忘了成功和错误事件是异步的。嗯,我还是想知道为什么浏览器崩溃了......
  • 这是正确的。异步回调可防止深度堆栈,因为调用函数在回调开始之前完全退出。
  • -1 Not true。在特殊情况下 jQuery.ajax 可以阻塞。即错误处理程序被同步调用。
【解决方案2】:
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 来破坏调用堆栈。

【讨论】:

    【解决方案3】:

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

    附带说明,您应该将 if 语句更改为类似

    的错误语句
       if(jqxhr.responseText == "timeout"){
          getData();
       }
    

    请参阅此处了解原因:jQuery Ajax error handling, show custom exception messages

    【讨论】:

      猜你喜欢
      • 2015-04-22
      • 2014-04-17
      • 1970-01-01
      • 2010-11-30
      • 2016-04-26
      • 2012-09-23
      • 2010-12-04
      • 2011-09-21
      • 2014-04-13
      相关资源
      最近更新 更多