2

我用短轮询(AJAX 刷新)制作了一个简单的 PHP jQuery 聊天应用程序。就像,每 2 - 3 秒它会询问新消息。但是,我读到长轮询对于聊天应用程序来说是一种更好的方法。所以,我浏览了一些长轮询脚本。我做了这样的:

Javascript:

$("#submit").click(function(){
    $.ajax({
        url: 'chat-handler.php',
        dataType: 'json',
        data: {action : 'read', message : 'message'}
    });
});

var getNewMessage = function() {
    $.ajax({
        url: 'chat-handler.php',
        dataType: 'json',
        data: {action : 'read', message : 'message'},
        function(data){
            alert(data);
        }
    });

    getNewMessage();
}

$(document).ready(getNewMessage);

PHP

<?php
    $time = time();
    while ((time() - $time) < 25) {
        $data = $db->getNewMessage ();

        if (!empty ($data)) {
            echo json_encode ($data);
            break;
        }

        usleep(1000000); // 1 Second
    }
?>

问题是,一旦getNewMessage()启动,它就会执行,除非它得到一些响应(来自 chat-handler.php)。它递归执行。但是,如果有人想在两者之间发送消息,那么实际上该函数($("#submit").click())永远不会像getNewMessage()仍在执行中那样执行。那么有什么解决方法吗?

4

2 回答 2

5

我强烈建议您阅读两件事:长轮询背后的想法和 jQuery 回调。我将快速介绍两者,但仅在此框允许的范围内详细介绍。

长轮询

长轮询背后的想法是让网络服务器在返回请求时人为地“减慢”速度,以便它等待直到事件出现,然后立即提供信息并关闭连接。这意味着您的服务器将闲置一段时间(好吧,不是闲置,但您知道我的意思),直到它最终获得消息通过的信息,将其发送回客户端,然后继续下一个一。

在 JS 客户端,效果是延迟了 Ajax回调(这是重要的一点)。

jQuery .ajax()

$.ajax()立即返回。情况不妙。您有两种选择来解决这个问题:

  • 在成功和错误回调函数中绑定您的递归调用(这很重要。错误函数很可能由于超时而出现)
  • (见下文):

用这个:

var x = $.ajax({blah});
$.when(x).done(function(a) { recursiveCallHere(); });

两者最终都等同于同一件事。您在回调而不是在启动时触发递归。

PS:怎么了sleep(1)

于 2012-11-17T22:55:48.290 回答
3

在长轮询中,当您收到前一个请求的数据时,应该启动新请求。否则,您将在浏览器冻结中无限递归。

var getNewMessage = function() {
    $.ajax({
        url: 'chat-handler.php',
        dataType: 'json',
        data: {action : 'read', message : 'message'},
        success: function(data) {
            alert(data);

            getNewMessage();   // <-- should be here
        }
    });
}
于 2012-11-17T22:53:59.397 回答