重复调用JavaScript函数而不获取stackoverflow

时间:2014-03-10 18:22:32

标签: javascript jquery ajax

关于我想要做的事情的一点背景:
我正在尝试创建一个实时聊天应用程序,它使用ajax重复检查服务器上的新消息 这里的不同之处在于我使用long-polling技术,其工作原理如下:

  1. Java-Script使用ajax
  2. 向服务器发送请求
  3. 如果服务器有新消息,则会使用新消息进行响应
  4. 如果服务器没有新消息,它根本不返回任何内容,请求仍然存活(仍然连接到等待响应的服务器)
  5. 一旦服务器收到新消息,它会立即响应新消息,该消息被保留/等待响应
  6. <小时/>

    我想做什么

    我对如何编写客户端scipt很困惑。 根据上面的描述,脚本应该

    1. 创建请求
    2. receiving content上,执行功能(更新聊天框),然后再次发送请求
    3. timeout上,只需再次发送请求,只需等待响应直到超时
    4. <小时/>

      我的尝试

      所以这是我在主页中的脚本:

      <script type="text/javascript">
          $(document).ready(function() {
              getMsg();
          });
      
          function getMsg() {
              var time = Math.floor(Date.now() / 1000);
      
              $.ajax({
                  url: "get_message.php?lastupdate=" + time,
                  type: "GET",
                  dataType: "json",
                  timeout: 15000, //15 second timeout
                  success: function(response) {
                      $('#chatBox').append("> " + response + "<br/>");
                      getMsg();
                  },
                  error: function(x, t, m) {
                      getMsg();
                  }
              });
          }
      </script>
      

      <小时/>

      问题

      如您所见,在errorsuccess我正在调用getMsg()函数中的getMsg()函数。我不冒运行堆栈溢出的风险吗?我的意思当然这几乎是不可能的,因为这需要大量的递归,但仍然感觉像一个糟糕的编程方法...

      是否有另一种方法可以在脚本中执行此操作:

      1. 创建请求
      2. 在接收内容时,执行功能(更新聊天框),然后再次发送请求
      3. On Time Out,只需重新启动功能
      4. 感谢您花时间阅读本文!

4 个答案:

答案 0 :(得分:3)

  

我不会冒着堆栈溢出的风险吗?

简答:

没有

答案很长:

当您致电$.ajax时,getMsg的当前实例等待以完成AJAX请求。它只是绑定了你拥有的所有事件处理程序,然后说“好吧,我已经完成了”

function getMsg() {
    var time = Math.floor(Date.now() / 1000);

    $.ajax({
        // all your options
    });

    // alright, I'm done
}

所以它返回。

为什么?,你问。因为AJAX中的“A”代表asynchronous。这意味着当您启动AJAX请求时,其他所有内容都可以继续。

当您在处理程序中调用getMsg时,它是 递归的实例。运行中永远不会有多个getMsg。没有递归。没有堆栈溢出。没问题。

答案 1 :(得分:1)

jQuery还支持承诺上的always property。因此,为了更简洁,您可以在always块中执行getMsg()调用

.always(getMsg);

您不必担心递归,因为它只会在完成后触发。

答案 2 :(得分:1)

此类代码中没有危险

只需将getMsg()置于'完成'属性(以便有一个整点来调用函数),就像那样

<script type="text/javascript">
    $(document).ready(function() {
        getMsg();
    });

    function getMsg() {
        var time = Math.floor(Date.now() / 1000);

        $.ajax({
            url: "get_message.php?lastupdate=" + time,
            type: "GET",
            dataType: "json",
            timeout: 15000, //15 second timeout
            success: function(response) {
                $('#chatBox').append("> " + response + "<br/>");
            },
            complete: getMsg // code will be executed on success/error
        });
    }
</script>

你必须记住 - 如果反应很快 - 你会得到很多请求 - 所以也许限制时间为15秒分钟

<script type="text/javascript">
    $(document).ready(function() {
        getMsg();
    });

    function getMsg() {
        var time = Math.floor(Date.now() / 1000);

        $.ajax({
            url: "get_message.php?lastupdate=" + time,
            type: "GET",
            dataType: "json",
            timeout: 15000, //15 second timeout
            success: function(response) {
                $('#chatBox').append("> " + response + "<br/>");
            },
            complete: function(){
                setTimeout(getMsg, 15000); // call with delay
            }
        });
    }
</script>

答案 3 :(得分:0)

function getMsg() {

    var time = Math.floor(Date.now() / 1000);
    var settings = {
        url: "get_message.php?lastupdate=" + time,
        type: "GET",
        dataType: "json",
        timeout: 15000, //15 second timeout
    };

    var req = $.ajax(settings);

    req.done(function(msg){$('#chatBox').append("> " + response + "<br/>");});

    req.fail(function(msg){$('#chatBox').append("> Network offline<br/>");});

    req.complete(getMsg); //runs after error/and success
}