EventSource


<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>EventSource</title>
</head>
<body>
<script>
    window.onload=function(){
        name();
        function name(){
            var username=prompt("請輸入您的昵稱");
            if(!username){
                return false;
            }
            var xml=new XMLHttpRequest();
            xml.open("POST","/addUser");
            xml.send("name="+username);
            xml.onreadystatechange=function(){
                if(xml.status=200&&xml.readyState==4){
                    var res=JSON.parse(xml.responseText)
                    if(res.success=="ok"){
                        alert("歡迎你的加入");
                        window.hiddenValue.value=res.name;
                        var es = new EventSource("/chat");
                        es.addEventListener("message", function(e){
                            var temp=document.createElement("li");
                            temp.innerHTML= e.data;
                            window.message.scrollIntoView();
                            window.content.appendChild(temp);
                        },false);
                    }else{
                        alert(res.msg+",如果你還想加入,行刷新重新輸入用戶名稱");
                        //本來用的遞歸,但是體驗不好,就改了
                        //name();
                    }
                }
            }
        }
        var div=document.getElementsByTagName("div")[0]
        div.style.width=window.innerWidth+"px";
    }
    function sendMessage(){
        var message=window.message.value;
        if(message.trim()){
          var b=new XMLHttpRequest();
            b.open("POST","/chat");
            b.send("message="+window.message.value+"&name="+ window.hiddenValue.value);
        }
    }

</script>
<div>
    <ul id="content">
    </ul>
</div>
<input type="text" name="message" id="message" /><input type="button" value="發送" onclick="sendMessage()"/>
<input type="hidden" id="hiddenValue">
</body>
</html>
View Code
var server=require("http");
var url=require("url");
var file=require("fs");
var querystring=require("querystring");
var clientName=[];
var responseArray=[];

    server.createServer(function (request, response) {
        var message="";
        var name="";
       var urlContent=url.parse(request.url);

        //首頁
        if(urlContent.pathname=="/"){
            response.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
            file.readFile("../views/Index.html",function(err,data){
             response.end(data);
         })
            return false;
        }
       else if(urlContent.pathname=="/chat"){

            //發送消息
            if(request.method=="POST"){

                //並不能根據response得到正確的name索引,所以前台傳遞name
                request.on("data",function(data){
                    data= querystring.parse(data.toString());
                    message+=decodeURIComponent(data.message.trim());
                    name+=decodeURIComponent(data.name.trim());
                })
                request.on("end",function(){
                    responseArray.forEach(function(i){
                        i.write("data:"+name+"說:"+message+"\n\n");
                    })
                })
                response.end();
            }else{

                //建立長連接,保存相應
                responseArray.push(response);
                response.writeHead(200,{"Content-Type":"text/event-stream"});
                response.write("data:已連接至服務器\n\n");
                request.connection.on("end",function(){
                    var index=responseArray.indexOf(response)
                    clientName.splice(index,1);
                    responseArray.splice(index,1);
                    response.end();
                })
            }
        }else if(urlContent.pathname=="/addUser"){

            //添加用戶名
            request.on("data",function(data){
                data= querystring.parse(data.toString().trim());
                name+=decodeURIComponent(data.name.trim());
            });
            request.on("end",function(){
                 response.writeHead(200,{"Content-Type":"text/json;charset=utf-8"});
                  if(clientName.some(function(i){
                          if(i==name) return true;
                      })){
                     response.write("{\"success\":\"fail\",\"msg\":\"用戶名重復\"}")
                 }else{
                     response.write("{\"success\":\"ok\",\"name\":\""+name+"\"}");
                     responseArray.forEach(function(i){
                         i.write("data:歡迎"+name+"的加入"+"\n\n");
                     })
                     clientName.push(name);
                 }
                response.end();

            })
        }
        else{
            response.writeHead(404,{"Content-Type":"text/json"});
            response.end();
        }
}).listen(8012);
View Code

后台使用Node.js  博主是一個新人,會有很多不太適合的代碼,希望大家能多多幫助。代碼中注意路徑問題。代碼仍有缺陷,現在連接斷開,不一定能夠刪除用戶名稱。以下的總結都是基於上面的代碼的,如果有其他情況,麻煩您給我說一下,謝謝。

 
可以跟服務器建立一個保持連接狀態的連接,這樣服務器能在服務端來對客戶端推送信息。服務端在推送的時候要注意格式。write的內容必須是data:內容的,當write中的內容 有一個空行的時候就會推送消息,推送后,會觸發EventSource的message事件,事件對象的data屬性為推送的消息內容。
當write的時候發現客戶端不再保持連接的時候,就會斷開連接,如果還在write,就會觸發write after end錯誤。只有服務端第一次wirte的時候才算連接成功,第一次write即使沒有空格不進行推送,客戶端也會得到200的狀態,正式建立連接。如果服務端沒有進行及時的write,則客戶端認為還在請求過程中,等待服務端響應,會有一個等待時間,在等待的時間內write會正確的建立200鏈接。如果超過等待時間還是沒有write,則請求將會失敗,將重新發起請求。如果服務端明確發回404,並且response結束,則不會再次發出請求,否則,長連接請求會一直等待正式建立連接,並過時,再請求。
第一個長連接請求在進行請求的時候,一直沒有建立正式的連接,超時后,會再次發送一個連接,在Chrome中觀看的話,同一個network發了兩次請求,但是這兩次請求的是不同的請求
 
open事件為服務器連接打開的時候觸發
error當發生錯誤的時候出發
 
如果服務器一直不觸發messag事件,則過了一段時間后,不管還以前的連接是否還在,都會重新發起一個請求。服務器與客戶端針對一個EventSource的request和response只存在一個,用前面的response.write的時候,將不會推送到客戶端(此response已經被客戶端放棄),如果連接建立后,服務器停掉了,則客戶端會一直發送長連接請求。當在客戶端使用eventsource的close或者關閉網頁的時候,觸發自己和服務器對應的request.connection的end事件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM