javascript和jQuery實現網頁即時聊天的ajax長輪詢_javascript技巧

來源:互聯網
上載者:User

介紹

大家都知道,HTTP協議是一個屬於應用程式層的物件導向的協議,HTTP 協議一共有五大特點:

1、支援客戶/伺服器模式;

2、簡單快速;

3、靈活;

4、無串連;

5、無狀態。

所以一次的請求都是一個單獨的事件,和前後都沒有聯絡。所以我們在解決網頁即時聊天時就遇到一個問題,如何保證與伺服器的長時間聯絡,從而源源不段地擷取資訊。

一直以來的方式無非有這麼幾種:

1、長串連,即伺服器端不斷開聯絡,PHP伺服器端用ob系列函數來不停的讀取輸出,但是相當耗費伺服器資源。

2、Flash socket,flash的as3語言,建立一個socket伺服器用來處理資訊。

3、輪詢,顧名思義就是不停地發送查詢訊息,一有新訊息立刻更新,但是會有多次無用請求。

4、長輪詢,是輪詢的升級版,需要伺服器端的配合。

5、websocket,HTML5的通訊功能,建立一個與伺服器端的專用介面ws協議來進行通訊,相容可能成為問題。

這篇博文總結一下用JS和JQ兩種方式(其實不同就是js和jq的實現),實現AJAX長輪詢。

長輪詢的思想:

如圖:用AJAX發送詢問資訊,伺服器在沒有資訊要返回的時候進入無限等待。由於AJAX非同步特性,PHP在伺服器端執行等待不會影響到頁面的正常處理。一旦伺服器查詢到返回資訊,伺服器返回資訊,AJAX用回呼函數處理這條資訊,同時迅速再次發送一個請求等待伺服器處理。

與傳統輪詢相比,長輪詢在伺服器沒的返回資訊的時候進入等待,減少了普通輪詢伺服器無數次的空回複。可以這樣認為,長輪詢使伺服器每次的返回更有目的性,而不是盲目返回。

長輪詢的伺服器端實現:

聊天資訊儲存:

資料庫設計為資訊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請求函數,每次查詢時被調用,當沒有資訊返回時,伺服器端被擱置,當前頁面正常執行;當有資訊返回時,函數處理返回的資料,並迅速再次調用此函數發送一次請求。

用原生JS:

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,即,新添加進去的資訊。

好了,本文到此就結束了,利用本文的範例程式碼一個簡單的聊天室程式就做好了,感興趣的可以快快實踐下了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.