Javascript 如何在不使用setInterval/timeout的情况下检查实时更新?

Javascript 如何在不使用setInterval/timeout的情况下检查实时更新?,javascript,ajax,comet,Javascript,Ajax,Comet,建立一个社交网络,我正在尝试获取实时通知。目前,站点使用setInterval每隔几秒钟发送一个AJAX请求。它看起来像这样: setInterval ( function(){ url = base_dir+"/ajax/file.php"; data = "data=someData"; $.ajax({ type: "POST", url: url, data: data, dataType: "jso

建立一个社交网络,我正在尝试获取实时通知。目前,站点使用setInterval每隔几秒钟发送一个AJAX请求。它看起来像这样:

setInterval ( function(){
    url = base_dir+"/ajax/file.php";
    data = "data=someData";
    $.ajax({
        type: "POST",
        url: url,
        data: data,
        dataType: "json",
        beforeSend: function(x) {
            if(x && x.overrideMimeType) {
                x.overrideMimeType("application/json;charset=UTF-8");
            }
        },
        success: function(JSON){
            // retrieve data here   
        }
    });
}, 5000);
这很好,但我非常担心会造成服务器过载。我尝试了comet技术,但由于某些原因,它发送的请求比上述代码多得多。 有没有其他更有用的技术来实时推送这些数据

编辑: 为了实现长轮询,我使用了以下方法(使用了这里提到的示例:):

有一种可能,我可能没有正确理解彗星原理

PHP代码:

// Checks for new notifications, and updates the title and notifications bar if there are any
 private static function NotificationsCounter (){
    //self::$it_user_id                                     = query that retrieves my id for further checks;                                                        
    //$friend_requests_count                                = query that retrieves the friend requests count;
    //$updates_count                                        = query that retrieves the updates count;               
    $total_notifications                                    = $friend_requests_count+$updates_count;

    if ($total_notifications > 0) $addToTitle = "(".$total_notifications.")";
    else $addToTitle = "";

    if ($updates_count > 0) $counterHTML = "<span class='notification_counter' id='updates_counter' style='float: right;'>".$updates_count."</span>";
    else $counterHTML = "";

    $data = array("counter"=>$total_notifications,"addToTitle"=>$addToTitle,"counterHTML"=>$counterHTML,);
    echo json_encode($data); // parse to json and print
}
//检查新通知,如果有,更新标题栏和通知栏
私有静态函数通知中心(){
//self::$it\u user\u id=检索我的id以进行进一步检查的查询;
//$friend\u requests\u count=检索朋友请求计数的查询;
//$updates\u count=检索更新计数的查询;
$total_notifications=$friend_requests_count+$updates_count;
如果($total_notifications>0)$addToTitle=“(“$total_notifications”)”;
else$addToTitle=“”;
如果($updates_count>0)$counterHTML=“”.$updates_count.”;
else$counterHTML=“”;
$data=array(“计数器”=>$total_通知,“addToTitle”=>$addToTitle,“计数器html”=>$counterHTML,);
echo json_encode($data);//解析为json并打印
}

既然Facebook也使用PHP,他们是如何做到的?

你应该使用websockets。您可以连接到服务器并在消息处理程序上注册。每当服务器有任何东西要发送给客户机时,就会调用您的处理程序。不需要超时

检查浏览器中是否支持websocket。到目前为止,只有Chrome、Opera和Safari支持它们

if ('WebSocket' in window){
   /* WebSocket is supported. You can proceed with your code*/
} else {
   /*WebSockets are not supported. Try a fallback method like long-polling etc*/
}
连接

var connection = new WebSocket('ws://example.org:12345/myapp');
处理者

connection.onopen = function(){
   console.log('Connection open!');
}

connection.onclose = function(){
   console.log('Connection closed');
}

connection.onmessage = function(e){
   var server_message = e.data;
   console.log(server_message);
}

文档:

一旦WebSocket在主要浏览器中得到更普遍的实现,它将是一条发展之路——我想至少需要5年的时间

上次我听说Facebook聊天使用comet和一大堆服务器。如果你想要更轻的东西,我可以想出两个选择

  • 缩短轮询间隔。这是一个严格的用户界面问题-用户可能有一个完全可以接受的体验,时间间隔长达几分钟。唯一可以确定的方法是通过用户测试,但每5秒轮询一次可能会有些过头。无论您选择哪种时间间隔作为最佳时间间隔,这都会为您提供一种快速扩展的方法,如果您受到影响,只需加快时间间隔,直到服务器停止融化

  • 使用HTTP验证缓存。如果服务器仅在内容自上次请求后发生更改时返回响应正文,则可以使请求更加轻量级。您必须使用ETag或Last Modified标头和服务器上的轻量级修改检查系统构建自定义的内容,但这可能会节省一些字节


  • 您可能想研究WebSocket的使用。能否发布用于长轮询技术的代码?使用HTTP可以做的事情不多。我添加了脚本。谢谢你的时间!您在服务器端配置了超时设置吗?我不确定。。。我该怎么做呢?最新版本的Firefox支持sockets,同时也支持IE10websocket@sdespont这是个好消息。。。知道Hixie是否受支持吗?我如何用PHP实现这一点?好吧,这在WAMP上非常有效,但在将其上传到服务器后,由于socket_bind()行,我一直得到“地址已在使用”。尝试过“sou_REUSEADDR”的事情,还是没有运气。我用谷歌搜索了一遍又一遍,找不到解决办法。有什么想法吗?5年后,正如我所希望的,WebSocket在所有主流浏览器中都得到了本地支持。我用github写了一个最简单的例子
    connection.onopen = function(){
       console.log('Connection open!');
    }
    
    connection.onclose = function(){
       console.log('Connection closed');
    }
    
    connection.onmessage = function(e){
       var server_message = e.data;
       console.log(server_message);
    }