Tornado+Layui(八)Tornado+Layui+WebSocket 前後端分離

目的:

         實現Tornado主動推送數據到前端

過程:

         1、Layui 中Websocket的 js代碼

 //此時的table只是爲了渲染表格
        table.render({
            elem: '#current_time_msg' // table標籤的ID
            , data: []
            , id: 'current_msg' // 爲了表格重載能找到這表格
            , cols: [[
                {field: 'ID', title: 'NO'}
                , {field: 'MsgType', title: '類型', templet: '#MsgTypeTpl'}
                , {field: 'CardNum', title: '卡號'}
                , {field: 'UserName', title: '人員'}
                , {field: 'DeptName', title: '部門'}
                , {field: 'ControlerName', title: '地點'}
                , {field: 'DoorName', title: '門名稱'}
                , {field: 'EventTime', title: '時間'}
            ]]
            , page: {theme: '#1E9FFF'}
            ,limit:150  //一頁顯示150條數據
            ,limits:[150]  // 分頁只設置150,否則爲10,20,30....條
        });
        //需要實時後端推送數據給前端
        var ip = window.location.href;
        ip = ip.substring(7, ip.lastIndexOf(':'));
        var ws = null;
        var websocket = null;
        //判斷當前瀏覽器是否支持WebSocket
        if ('WebSocket' in window) {
            //連接後端websocket
            ws = new WebSocket('ws://' + ip + ':8977/ws/time_news');
        } else {
            layer.msg('Dont  support websocket')
        }

        //連接發生錯誤的回調方法
        ws.onerror = function () {
            layer.msg('Error')
        };
        //連接成功建立的回調方法
        ws.onopen = function () {
            layer.msg('Open')
        };
        //接收到消息的回調方法
        ws.onmessage = function (event) {
             // websocket只能傳str類型,否則在瀏覽器的console中WS選項卡里請求攔截的data爲空
            console.log(typeof (JSON.parse(event.data)), JSON.parse(event.data));
             var obj = JSON.parse(event.data);
            table.reload('current_msg', {
                elem: '#current_time_msg'
                , data: JSON.parse(event.data)
                , page: {theme: '#1E9FFF'}
                ,limit:150
                ,limits:[150]
            });

        };
        // 連接關閉的回調方法
        ws.onclose = function () {
            layer.msg('Close')
        };
        //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常
        window.onbeforeunload = function () {
            ws.close()
        };

        //關閉連接
        function closeWebSocket() {
            ws.close();
            window.clearInterval(intervalId)
        }

        //發送消息
        function send() {
            var message = document.getElementById('current_time_msg').value;
            ws.send(message);
        }

        2、Tornado Websocket代碼

                ①、定義Websocket類

class WSTimeNewsHandler(WebSocketHandler):
    # 用於多用戶連接
    users = set()

    def open(self):
        print('WebSocket opened!', self)
        self.users.add(self)

    def on_message(self, message):
        print(message)
        for user in self.users:
            user.write_message(message)
    
    #自定義發送數據方法
    @classmethod
    def update_data(self, message):
        for user in self.users:
            user.write_message(message)

    def on_close(self):
        print('WebSocket closed!')
        self.users.discard(self)

    # 允許跨域通訊,解決403問題
    def check_origin(self, origin):
        return True

            ②、處理數據方法,用於調用  WSTimeNewsHandler.update_data()——>即Websocket發送數據的方法

#該方法是監聽MySQL數據庫表是否有新數據,以ID爲判斷基礎,有新數據則推送,無則不推送


def card_event():
    print('我進入到CardEvent方法')
    id_data = [0]
    # 默認查詢今天時間事件
    moring_time = datetime.datetime.now().strftime('%Y-%m-%d 00:00:00')
    night_time = datetime.datetime.now().strftime('%Y-%m-%d 23:59:59')
    with session_maker() as session:
        res = session.query(func.max(BusinessEvent.EventID)).first()[0]
        if res >= id_data[0]:
            id_data[0] = res
            print('我要進入查詢語句了')                                  
            res_data=session.query.filter(BaseEventtype).filter(
                                    SetID,CardNum,UserName,DeptName,ControlerName,
                                    DoorName,EventTime,EventContent).group_by(
                                    EventTime).order_by(EventTime.desc()).all()
            res = []
            for i, item in enumerate(res_data):
                result = {'ID': i + 1, 'MsgType': item[0], 'CardNum': item[1], 'UserName': item[2],
                          'DeptName': item[3],
                          'ControlerName': item[4], 'DoorName': item[5],
                          'EventTime': item[6].strftime('%Y-%m-%d %H:%M:%S'), 'EventContent': item[7]}
                res.append(result)
            # 把打包好的數據做分頁
            res_limit_data = pagination(1, 150, len(res), res)
            print(res_limit_data)
            # 調用WebSocket發送數據方法
            WSTimeNewsHandler.update_data(json.dumps(res_limit_data))
        else:
            print(res)

         ③、調用方法 參雜在其同一個界面的請求裏

class EventHandler(BaseHandler):
    def post(self):
        card_event()
        #具體查庫封裝數據就不寫了,根據實際情況寫
        ...

         ④、請求地址

    url_client = [
                    (r"/ws/time_news", WSTimeNewsHandler),
                    (r"/api/event", EventHandler), 
                 ]

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章