PHP 簡易聊天室 利用redis的訂閱發佈功能

demo:
http://139.196.97.20:8083/api/chat/list

前言:
這個種方式太耗redis鏈接數,每次訂閱都會新起一個進程,僅供練手使用,切勿用於生產環境。

原理:
1.PHP提供兩個接口,訂閱,發佈,redis就有提供
2.訂閱接口會卡住,不會立刻response,直至有發佈的消息
3.前端須要在一次訂閱請求成功或失敗後當即從新發一個訂閱請求,以避免錯漏信息

html

後臺代碼(用的laravel框架,只要能調用redis,實現一致便可):前端

// 訂閱接口
public
function subscribe(Request $request) { Redis::subscribe([self::CHATROOMCHANNEL], function ($message) { echo json_encode($this->rtnSucc($message)); exit; }); }
// 發佈接口
public function publish(Request $request) { $num = Redis::publish(self::CHATROOMCHANNEL, $request->input('say', '對方沒有說話')); if ($num) { return $this->rtnSucc($num); } else { return $this->rtnErr(100, "發送失敗"); } } private function rtnSucc($data) { return ["rtn" => 0, "msg" => "", "data" => $data]; } private function rtnErr($rtn, $msg = "") { return ["rtn" => $rtn, "msg" => $msg, "data" => ""]; }

 

前端代碼:laravel

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>200OK ChatRoom</title>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #input_box {
            width: 92%;
            height: 100px;
            margin: 0 auto;
            display: block;
            border-radius: 2px;
        }

        #btn {
            height: 30px;
            text-align: center;
            font-size: 16px;
            background-color: #E91E63;
            color: #fff;
            margin: 10px 10px 0 10px;
            border-radius: 2px;
            line-height: 30px;
        }

        #content {
            margin: 0 10px;
            font-size: 16px;
            color: #795548;
        }
    </style>
</head>
<body>

<div id="content">
    <p>200 OK ChatRoom!</p>
</div>
<textarea id="input_box" placeholder="輸入你想說的話"></textarea>
<div id="btn">發射!</div>
<script src="/js/zepto.js"></script>
<script src="/js/md5.min.js"></script>
<script>
    // dom
    let $input_box = $("#input_box");
    let $content = $("#content");
    let $btn = $("#btn");
    let myName = getRandomName();

    main();

    // 入口
    function main() {
        bindEvent();
        subscribe();
        $content.append(pp("你叫:" + myName));
    }

    // 監聽事件
    function bindEvent() {
        $btn.on("click", function () {
            say();
        });

        $input_box.bind('keyup', function (e) {
            if (13 === e.keyCode) {
                say();
            }
        });
    }

    //
    function say() {
        var str = getC().trim();
        if (!str) {
            error("請輸入內容");
            return;
        }
        publish(namePrefix() + str, function (rp) {
            $input_box.val("");
            $input_box.focus();
        });
    }

    // 獲取輸入框內容
    function getC() {
        return $input_box.val();
    }

    // 訂閱 回調以後繼續訂閱
    function subscribe(callback) {
        $.ajax({
            type: 'GET',
            url: '/api/chat/subscribe',
            data: {},
            dataType: 'json',
            timeout: 10000,
            success: function (data) {
                if (0 === data.rtn) {
                    $content.append(pp(data.data));
                }
                subscribe();
            },
            error: function (xhr, type) {
                // 防止雪崩
                setTimeout(function () {
                    subscribe();
                }, 1000);
            }
        });
    }

    // 發佈
    function publish(str, callback) {
        $.get('/api/chat/publish?say=' + str, function (response) {
            callback(response);
        });
    }

    function pp(str) {
        return "<p>" + str + "</p>"
    }

    function namePrefix() {
        return myName + ": ";
    }

    // 錯誤處理
    function error(str) {
        alert(str);
    }

    // 生成隨機姓名
    function getRandomName() {
        var familyNames = new Array(
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", "",
            "", "", "", "", "", "", "", "", "", ""
        );
        var givenNames = new Array(
            "子璇", "", "國棟", "夫子", "瑞堂", "", "", "", "國賢", "賀祥", "晨濤",
            "昊軒", "易軒", "益辰", "益帆", "益冉", "瑾春", "瑾昆", "春齊", "", "文昊",
            "東東", "雄霖", "浩晨", "熙涵", "溶溶", "冰楓", "欣欣", "宜豪", "欣慧", "建政",
            "美欣", "淑慧", "文軒", "文傑", "欣源", "忠林", "榕潤", "欣汝", "慧嘉", "新建",
            "建林", "亦菲", "", "冰潔", "佳欣", "涵涵", "禹辰", "淳美", "澤惠", "偉洋",
            "涵越", "潤麗", "", "淑華", "晶瑩", "凌晶", "苒溪", "雨涵", "嘉怡", "佳毅",
            "子辰", "佳琪", "紫軒", "瑞辰", "昕蕊", "", "明遠", "欣宜", "澤遠", "欣怡",
            "佳怡", "佳惠", "晨茜", "晨璐", "運昊", "汝鑫", "淑君", "晶瀅", "潤莎", "榕汕",
            "佳鈺", "佳玉", "曉慶", "一鳴", "語晨", "添池", "添昊", "雨澤", "雅晗", "雅涵",
            "清妍", "詩悅", "嘉樂", "晨涵", "天赫", "玥傲", "佳昊", "天昊", "萌萌", "若萌"
        );

        var i = parseInt(10 * Math.random()) * 10 + parseInt(10 * Math.random());
        var familyName = familyNames[i];

        var j = parseInt(10 * Math.random()) * 10 + parseInt(10 * Math.random());
        var givenName = givenNames[i];

        return familyName + givenName;
    }
</script>
</body>
</html>
相關文章
相關標籤/搜索