JavaScript与jQuery实现AJAX长轮询实时聊天

作者:青柠

时间:2026-10-30

浏览:539

本文详解如何利用JavaScript原生及jQuery库实现基于AJAX的长轮询技术,构建网页实时聊天功能。通过解析HTTP无状态特性,对比长连接、Flash Socket、普通轮询及WebSocket等方案,重点阐述长轮询在减少无效请求方面的优势。内容涵盖MySQL数据库设计、PHP后端无限等待逻辑、以及前端的异步请求处理与POST发送实现,提供完整代码思路与注意事项。

文章目录

介绍

HTTP协议特点与实时通信挑战

HTTP协议作为应用层面向对象的协议,具备五个显著特征:

1、支持客户/服务器模式;

2、简单快速;

3、灵活;

4、无连接;

5、无状态。

由于每次HTTP请求都是独立事件,前后请求互不关联,因此在开发网页实时聊天应用时,核心挑战在于如何维持与服务器端的长期连接,以确保持续获取信息。

常见实时通信方案对比

目前常见的解决方案主要包括以下几种:

1、长连接:服务器端保持连接不断开,例如PHP中使用ob系列函数持续读取输出,但这种方式对服务器资源消耗极大。

2、Flash Socket:利用Flash的AS3语言创建Socket服务器来处理信息交互。

3、普通轮询:即客户端不停地发送查询消息,一旦有新消息立即更新,但会产生大量无效的重复请求。

4、长轮询:这是轮询技术的升级版,需要服务器端进行配合支持。

5、WebSocket:HTML5提供的通信功能,通过建立专用接口ws协议进行通讯,但需考虑浏览器兼容性问题。

本文将总结使用JavaScript和jQuery两种方式(主要区别在于JS与JQ的实现差异)来实现AJAX长轮询。

长轮询原理与优势

长轮询的核心思想如下:

HTTP协议特点与实时通信挑战

如图:,通过AJAX发送询问信息,若服务器端暂无信息返回,则进入无限等待状态。得益于AJAX的异步特性,PHP在服务器端的等待过程不会影响页面的其他正常处理。一旦服务器查询到返回信息,便立即返回,AJAX通过回调函数处理该信息,并迅速再次发送新的请求以等待服务器处理。

与传统轮询相比,长轮询在服务器没有返回信息时进入等待状态,从而大幅减少了普通轮询中服务器无数次空回复的情况。可以认为,长轮询使服务器的每次返回更具目的性,避免了盲目返回数据。

服务器端数据库设计与PHP实现

接下来介绍长轮询在服务器端的实现方法:

聊天信息存储方案:

数据库表设计包含字段:信息ID(msgid)、发送人(sender)、接收人(receiver)、信息内容(content)。设置senderRead和receiverRead字段的目的是标记信息是否已被读取,读取后修改该标记,以此区分信息是否已读。


create table msg{

  msgid int not null primary key auto_increment,

  sender char(16) not null,

  receiver char(16) not null,

  content text, //信息内容用text类型,存储量可达到65535字符

  senderRead tinyint enum(0,1) default 0,

  receiverRead tinyint enum(0,1) default 0 //设置一个是否已读的flag标记

}

PHP脚本实现:

脚本的主要职责是处理来自AJAX的每次询问。AJAX每次询问时,脚本查询数据库以查看是否有新信息;如果没有,则使用usleep()函数等待一秒后再次查询,直到有新信息插入数据库并被查询到。脚本返回查询到的数据,并退出无限循环,结束脚本执行。


set_time_limit(0);//设置脚本超时时间为无限,不然在过了超时时间后脚本会自动关闭,轮询失败。
 $link=new mysqli("host","user","password","database");
 $search="select sender,receiver,content from msg where receiverRead=0 limit 1";//限制每次读出一条数据,便于修改其已读flag
 $change="update chat set receiverRead=1 where receiverRead=0 limit 1";
 while (true) { //进入无限循环
     $res=$link->query($sql); //查询结果
     if($res->num_rows!=0){ //当有未读信息时读取信息
        $link->query($change);//将信息的已读flag设为1
        $msg=$res->fetch_assoc();
        $jsonstr=json_encode($msg);//取到信息,将信息用转码为json格式,返回给JS
        echo $jsonstr;
        break;//输出信息后退出while循环,结束当前脚本
     }
   usleep(1000);//如果没有信息不会进入if块,但会执行一下等待1秒,防止PHP因循环假死。
 }

客户端AJAX请求处理

客户端实现方案:

客户端的主要任务是设置一个AJAX请求函数,每次查询时被调用。当没有信息返回时,服务器端处于搁置状态,当前页面可正常执行;当有信息返回时,函数处理返回的数据,并迅速再次调用此函数发送一次新的请求。

原生JS与jQuery实现代码

使用原生JavaScript实现:


function link(){
 var xhr=null;//先设置xhr为空,为了轮询时再次调用函数对xhr重用,引发错误
 xhr=new XMLHttpRequest();
 xhr.open('GET','serviceback.php',true);//第三个参数一定要设置为true,异步不阻塞,不会影响到后面JS的执行。
 xhr.send();
 xhr.onreadystatechange=function(){
     if (xhr.readyState==4) { 严密也可加使用(xhr.readyState==4 && xhr.status ==200)限定服务器响应码为200时才进行处理。
        if(xhr.responseText!=''){
           process... //服务器端返回信息,且返回信息不为空,则开始处理返回信息。
        }
    setTimeout("link()",300);
//递归再次调用link()函数,用setTimeOut()设置延时是因为服务器端进行sql操作时会耗时,当有新信息时,在服务器将要置已读flag为1还未成功时,AJAX可能已经又发出多条查询信息了,会导致一条信息多次返回。
    }
 };
}

使用jQuery插件实现:


var link={           //jQuery的AJAX执行的配置对象
  type:"GET",      //设置请求方式,默认为GET,
  async:true,      //设置是否异步,默认为异步
  url:"customback.php",
  dataType:"json",    //设置期望的返回格式,因服务器返回json格式,这里将数据作为json格式对待
  success:function (msg){
      process...
     setTimeout("link()",300);
  }              //成功时的回调函数,处理返回数据,并且延时建立新的请求连接
}
$.ajax(link);          //执行ajax请求。
]

发送功能与消息处理优化

程序功能扩充:

添加发送聊天窗口功能:

新建一个函数来处理AJAX的POST请求,通过AJAX将发信人、每次发送的信息内容、收信人发送到服务器端,并设置一个单独的PHP脚本来处理这些信息,将信息插入数据库。

需要注意的是,使用JS原生实现POST请求发送信息时,必须设置ajax对象的HTTP头,以模拟表单提交的操作:。

xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");

聊天室消息处理优化:

为了防止每次都查询到全部历史消息,我们对数据库的查询操作进行了调整。设置idflag=0,每次查询后,将idflag设置为查询到的数据的ID。在后续查询时,我们只查询比idflag大的ID,即仅获取新添加进去的信息。

至此,本文内容结束。利用本文提供的示例代码,一个简单的聊天室程序即可搭建完成,感兴趣的读者可以尽快进行实践。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章