Websocket Demo

參考資料

零、Introduce

  • WebSocket 規(guī)范定義了一種 API唧垦,可在網(wǎng)絡(luò)瀏覽器和服務(wù)器之間建立“套接字”連接旷痕。簡單地說:客戶端和服務(wù)器之間存在持久的連接,而且雙方都可以隨時開始發(fā)送數(shù)據(jù)。
  • 對于我們來說贯被,用來做即時通訊跟H5交互游戲都是不錯的選擇鞭光。
  • 注意事項:目前有部分瀏覽器不支持websocket,同時笋庄,使用websocket也必須服務(wù)器支持websocket效扫,有些代理服務(wù)器也不支持websocket。檢驗方法可參考 阮一峰教程直砂。

一菌仁、Example

時間軸側(cè)邊欄
時間軸主頁
  • 其中,時間軸的主題內(nèi)容便是使用websocket從服務(wù)器獲取json格式數(shù)據(jù)静暂,使用 onmessage 監(jiān)聽事件實(shí)時響應(yīng)渲染內(nèi)容济丘。相比Ajax,響應(yīng)速度更好;劣勢是websocket是多個用戶在一個會話層摹迷,用戶量過高時會影響性能疟赊。

二、Syntax

1. 連接&斷開

if(window.WebSocket != undefined) {    // 檢測是否支持websocket
        var connection = new WebSocket(socketUrl);
        // readyState為open時觸發(fā)
        connection.onopen = function wsOpen(event) {
            console.log("Connected to localhost:8080");
        };
        // readyState為close時觸發(fā)
        connection.onclose = function wsClose() {
            console.log("WebSocket is closed")
        };
        // 客戶端收到服務(wù)端信息觸發(fā)
        connection.onmessage = function wsMessage(event) {
            var msg = JSON.parse(event.data);
            myRender(msg.info);
            gotoPage();
        };
    }

2. 信息處理

connection.send( message );    // 發(fā)送信息
connection.onmessage = wsMessage;    // 接收信息
function wsMessage( event ) {
    console.log( event.data );
}
connection.onerror = wsError;    // 處理錯誤信息
  • 上面代碼的回調(diào)函數(shù)wsMessage的參數(shù)為事件對象 event 峡碉,該對象的 data 屬性包含了服務(wù)器返回的數(shù)據(jù)近哟。

三、代碼介紹

  • websocket.js:需要引入ws模塊
/*
 * author: Stngle
 * e-mail: 1113591198@qq.com
 */
 
// 獲取一個websocket server對象
var WebSocketServer = require('ws').Server;
// 創(chuàng)建ws服務(wù)器
var ws = new WebSocketServer({
    port: 1234  // 監(jiān)聽的端口
});
// 設(shè)置發(fā)送給客戶端的數(shù)據(jù)
var sendData = {
    info:[
        {
            id: "00000000",                             
            time: "0:00--0:27",                         
            imgSrc: "../images/00000001.png",   
            sort: "movie",          
            title:"微微一笑很傾城",                    
            brief: "導(dǎo)演:趙天宇<br/>主演:Angelababy/井柏然/李沁/譚松韻/李現(xiàn)",    
            locationUrl: "http://www.baidu.com",
            collection: "favorite_border"                                       
        },
        {
            id: "00000001",                             
            time: "0:00--0:27",                         
            imgSrc: "../images/00000001.png",   
            sort: "movie",          
            title:"微微一笑很傾城",                    
            brief: "導(dǎo)演:趙天宇<br/>主演:Angelababy/井柏然/李沁/譚松韻/李現(xiàn)",    
            locationUrl: "http://www.baidu.com",            
            collection: "favorite"                                  
        }
    ]
};
// 將發(fā)送數(shù)據(jù)decode為JSON格式
var sendDataDecode = JSON.stringify(sendData);
// 處理連接
ws.on('connection',
    function(socket) {
        socket.onmessage = message;
        socket.onclose = close;
        socket.onerror = error;
        socket.onopen = open;
        socket.send(sendDataDecode, function() {
        console.log("data has send");
    })
    });

function message(msg){
    //對接收到的消息做些什么
}
function error(err){
    // 消息出錯做什么
    console.log(err);
}
function close(){
    // 會話關(guān)閉做什么
    console.log("socket closed");
}
function open(){
    // 會話打開時
    console.log("socket opened");
}

node websocket.js    // 運(yùn)行該文件作為本地服務(wù)端
  • main.js:直接運(yùn)行即可
/*
 * author: Stngle
 * e-mail: 1113591198@qq.com
 */

/*
 * 全局配置參數(shù)
 */
var socketUrl = "ws://localhost:1234";      // 配置websocket URL

/*
 * 主函數(shù)入口
 */
$(document).ready(function() {
    sideBar();
    webSocket();
});

/*
 * sidebar:用于側(cè)邊欄菜單交互
 */
function sideBar() {
    // nav-left
    $("#menu").on("click",function(ev){
        $(".sidebar").animate({"left":0},500);
        ev.preventDefault();
        $("body").after("<div class='shade-layer'></div>");
        // shade-layer:hide
        $(".shade-layer").on("click",function(ev){
            $(".sidebar").animate({"left":"-100%"},500);
            $(".shade-layer").remove();
        })
    });
    // close -> shade-layer:hide
    $("#close").on("click",function(ev){
        ev.preventDefault();
        $(".sidebar").animate({"left":"-100%"},500);
        $(".shade-layer").remove();
    });

    $("body").on("touchstart",function(ev){
        startx = ev.originalEvent.targetTouches[0].pageX;
    });

    $("body").on("touchend",function(ev){
        endx = ev.originalEvent.changedTouches[0].pageX;
        if (endx - startx > 20) {
            $(".sidebar").animate({"left":0},500);
            $("body").after("<div class='shade-layer'></div>");
            // shade-layer:hide
            $(".shade-layer").on("click",function(ev){
                $(".sidebar").animate({"left":"-100%"},500);
                $(".shade-layer").remove();
            })
        }else if (endx - startx < -20) {
            $(".sidebar").animate({"left":"-100%"},500)
            $(".shade-layer").remove();
        }
    });
}
/*
 * 渲染info list的模板鲫寄,文本<br/>有效吉执,若要限制字?jǐn)?shù)可以在以下函數(shù)使用slice()方法
 * 二級跳轉(zhuǎn)鏈接放在.title的gotoUrl屬性中,供監(jiān)聽器gotoPage()回調(diào)時讀取
 */
function myRender(infos) {
    $(infos).map(function(index,info) {
        $(".info-list").append(
            '<div class="info">'+
                '<img src="' + info.imgSrc +  '"/>' +
                '<div class="text">' +
                    '<a class="title" gotoUrl="' + info.locationUrl + '"><span>' + info.title + '</span></a>' +
                    '<i  class="material-icons">' + iconSort(info) + '</i>' +
                    '<p class="brief">' + info.brief + '</p>' +
                    '<p><i class="material-icons">' + info.collection + '</i><i class="material-icons">share</i></p>' +
                '</div>' +
            '</div>'
            );
    })
}

/*
 * icon 分類地来,根據(jù)websock傳來的info.sort渲染icon
 */
function iconSort(info) {
    if(info.sort === "movie") {
        return "movie";
    }else if(info.sort === "") {
        return "";
    }else {
        return "";
    }
}
/*
 * websocket部分:
 */
function webSocket() {
    // 與本機(jī)的8080端口建立連接
    if(window.WebSocket != undefined) {
        var connection = new WebSocket(socketUrl);
        // readyState為open時觸發(fā)
        connection.onopen = function wsOpen(event) {
            console.log("Connected to localhost:8080");
        };
        // readyState為close時觸發(fā)
        connection.onclose = function wsClose() {
            console.log("WebSocket is closed")
        };
        // 客戶端收到服務(wù)端信息觸發(fā)
        connection.onmessage = function wsMessage(event) {
            var msg = JSON.parse(event.data);
            myRender(msg.info);
            gotoPage();
        };
    }
}
/*
 * 跳轉(zhuǎn)二級頁面的渲染示例
 * 先獲取gotoUrl屬性存儲的地址戳玫,再移除原有info-list中的內(nèi)容,再生成新的二級頁面
 */
function gotoPage() {
    $(".title").on("click", function() {
        var gotoUrl = $(this).attr("gotoUrl");
        $(".info-list").empty();
        $(".info-list").append(
            "<div class='pageSecondary'><a href='" + gotoUrl + "'><button>閱讀原文</button></a></div>"
            )
    })
}
  • index.html:作為本project的入口文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <title>時間軸</title>
    <link  rel="stylesheet">
    <link rel="stylesheet" href="main.css">
</head>
<body>
    <!-- topbar -->
    <nav>
        <a id="menu"><span class="nav-left"><i class="material-icons">menu</i></span></a>
        <span class="nav-right"><i class="material-icons">collections</i></span>
    </nav>
    <!-- sidebar -->
    <div class="sidebar">
        <ul>
            <a >
                <li class="sidebar-li sidebar-first"><i class="material-icons">find_in_page</i><span class="font">登錄</span><i class="material-icons sidebar-right" id="close">menu</i></li></a>
            <a href="#">
                <li class="sidebar-li"><i class="material-icons">autorenew</i><span class="font">刷新</span></li>
            </a>
            <a href="#">
                <li class="sidebar-li"><i class="material-icons">find_in_page</i><span class="font">幫助&amp反饋</span></li>

            </a>
            <a href="#">
                <li class="sidebar-li"><i class="material-icons">settings</i><span class="font">設(shè)置</span></li>
            </a>
            <a href="#">
                <li class="sidebar-li"><i class="material-icons">highlight_off</i><span class="font">注銷</span></li>
            </a>
        </ul>
    </div>
    <!-- 橫幅封面圖 -->
    <div class="cover">
        <img src="../images/cover.png" alt="封面圖片">
    </div>
    <!-- info list -->
    <div class="info-list">
        
    </div>
    <!-- <i class="material-icons">favorite</i> -->
    <script src="../jquery-3.1.1.js"></script>
    <script src="main.js"></script>

</body>
</html>
  • main.css:作為index.html的樣式表
*{
    margin: 0;
}
nav{
    background-color: rgb(2,168,243);
    padding-left: 5%;
    padding-right: 5%;
    padding-bottom: 6px;
    padding-top: 6px;
}
i{
    padding-top: 5px;
    padding-bottom: 5px;
}
.nav-left{
    color: #FFFFFF;
}
.nav-right{
    color: #FFFFFF;
    float: right;
}
.cover img{
    width: 100%;
    height: 
}


/* sidebar */
.shade-layer{
    position: absolute;
    left: 0%; 
    top: 0%;
    background-color: rgba(0,0,0,0.7);
    width: 100%;
    height: 100%;
    z-index: 99;
}
.sidebar{
    position: absolute;
    left: -100%;
    top: 0;
    height: 100%;
    width: 70%;
    background-color: #fff;
    z-index: 999;
}
.sidebar ul{
    padding: 0;
}
.sidebar a{
    color: #000;
    text-decoration: none;
    height: auto;
}
.sidebar-li{
    padding: 6px 5%;
    border-bottom: solid 1px #eee;
    list-style: none;
    background-color: #ffffff;
}
.sidebar-first{
    background-color: rgb(2,168,243);
    padding: 6px 5%;
    font-size: 0.9em;
}
.sidebar-right{
    float: right;
}
.font{
    padding-left: 5px;
    vertical-align: 3px;
}
#menu{
    display: inline-block;
}

/*info list*/
.info img{
    padding: 8px 2%;
    display: inline-block;
    border-radius: 40px;
    width: 18%;
    height: 18%;
    vertical-align: top;
}
.text{
    width: 70%;
    display: inline-block;
}
.text a{
    color: rgb(12,140,243);
    font-weight: bold;
    line-height: 20px;
    margin-left: 5%;
    padding-left: 20px;
    border-left: solid 2px rgb(64,148,199);
}
.text span{
    position: relative;
    top: 25px;
}
.text >i:first-of-type{
    display: block;
}
.text p{
    color: #333;
    margin-left: 5%;
    padding-left: 20px;
    border-left: solid 2px rgb(2,168,243);
}
p i:first-of-type{
    margin-left: 60%;
    color: #999;
}
p i{
    color: #999;
    margin-left: 5%;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末未斑,一起剝皮案震驚了整個濱河市咕宿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜡秽,老刑警劉巖荠列,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異载城,居然都是意外死亡肌似,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門诉瓦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來川队,“玉大人,你說我怎么就攤上這事睬澡」潭睿” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵煞聪,是天一觀的道長斗躏。 經(jīng)常有香客問我,道長昔脯,這世上最難降的妖魔是什么啄糙? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮云稚,結(jié)果婚禮上隧饼,老公的妹妹穿的比我還像新娘。我一直安慰自己静陈,他們只是感情好燕雁,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布诞丽。 她就那樣靜靜地躺著,像睡著了一般拐格。 火紅的嫁衣襯著肌膚如雪僧免。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天捏浊,我揣著相機(jī)與錄音猬膨,去河邊找鬼。 笑死呛伴,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的题翻。 我是一名探鬼主播狭郑,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼凝果,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了姐军?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤尖淘,失蹤者是張志新(化名)和其女友劉穎奕锌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體村生,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惊暴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了趁桃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辽话。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖卫病,靈堂內(nèi)的尸體忽然破棺而出油啤,到底是詐尸還是另有隱情,我是刑警寧澤蟀苛,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布益咬,位于F島的核電站,受9級特大地震影響帜平,放射性物質(zhì)發(fā)生泄漏幽告。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一裆甩、第九天 我趴在偏房一處隱蔽的房頂上張望评腺。 院中可真熱鬧,春花似錦淑掌、人聲如沸蒿讥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芋绸。三九已至媒殉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間摔敛,已是汗流浹背廷蓉。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留马昙,地道東北人桃犬。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像行楞,于是被迫代替她去往敵國和親攒暇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 最近筆者新參與的一個web項目子房,擬定采用vue2.0來編寫形用,期間遇到有關(guān)使用websocket的問題,記錄一下证杭,個...
    七寶琥珀閱讀 44,046評論 6 35
  • 寫作原因:公司這個月的項目計劃是優(yōu)化推送田度;目前我們推送用的個推(不是不好,項目限制)解愤,然后服務(wù)器那邊人員忙(本人...
    Thebloodelves閱讀 18,302評論 44 69
  • WebSocket簡介 談到Web實(shí)時推送镇饺,就不得不說WebSocket。在WebSocket出現(xiàn)之前送讲,很多網(wǎng)站為...
    吧啦啦小湯圓閱讀 8,155評論 15 75
  • 我在12年結(jié)束了學(xué)校的學(xué)習(xí)生涯兰怠,從此混溺于職場。這么多年過去李茫,唯一沒能改變的就是工資月月光揭保。最近一段時間,在還沒畢...
    Zmm就是我閱讀 305評論 0 0
  • 很多類似《人性的弱點(diǎn)》的書中,都定會強(qiáng)調(diào)做事專注的重要性宠互。每當(dāng)讀到這些文章中陳列的道理味榛,講述的案例時,我也深以為然...
    me揮之即去閱讀 165評論 0 1