iT邦幫忙

2021 iThome 鐵人賽

DAY 10
0
Modern Web

不只是串串API,新手前端30天系列 第 10

DAY10 - websocket前端實作-以vue.js為例

今天我們就來講一下,當我們專案中確定會導入websocket了,前端的工作流程會是怎樣,要怎麼跟後端溝通又要怎麼實作呢?

STEP1. websocket規格文件

其實跟API一樣,我們總要知道怎麼做跟後端溝通,才能進行。
文件裡要包含的東西基本上也就包含幾項資訊:

1. Websocket 連線資訊

前後端要開始啟動websocket通道,就必須要知道要要怎麼連,連去哪。
因此我們會需要 websocket的URL,可能也會有要給的參數從其他資訊傳入

URL ws://sample.com/infomation/{userId}/
Parameter(optional) userId: (從 http://sample.com/api/user API取得)

2. Websocket 發送資訊與通知訊息

什麼時候,後端會發送訊息給前端? 且前端得到的response是什麼呢?
這邊的資訊就會包含: trigger這個websocket發送訊息的時機點、還有在這個時機點回應的格式。才能讓前端知道,在怎樣的時間點會收到怎樣的資訊。

Trigger Point 當書本借閱狀態改變的時候
Response 格式 { "action": "BookStatusChange", content: {"id": 001}}

STEP2. 前端實作websocket

這邊分享一下自己在vue專案中建立的websocket作法

2-1. 利用vuex統一控管websockt傳來的通知

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
// 定義一個新的 Vue Store
const store = new Vuex.Store({
    state: {
        wsNotify: {},
    },
    mutations: {
        //當接收到最新的後端送來的websocket資訊,直接存到state中的wsNotify
        setWsNotify(state, param) {
            Vue.set(state, 'wsNotify', param);
        },
    }
    
})

2-2. 建立 ws.js 將所有websocket相關的事件流程統整 (在vue中我用mixin統整起來)

import { mapMutations } from 'vuex';
export const mixinWebsocket = {
    data(){
        return{
            ws: null,
        }
    },
    methods:{
         ...mapMutations(['setWsNotify']),
        //初始websocket
        initWebsocket(){
            let wsURL = `ws://sample.com/infomation/${userId}`;
            this.ws = new WebSocket(wsURL); //建立連線
            this.ws.onopen = this.websocketonopen;
            this.ws.error = this.websocketonerror;
            this.ws.onmessage = this.websocketonmessage;
            this.ws.onclose = this.websocketclose;
        },
        websocketonopen(){
            console.log('ws 連線成功~~');
        },
        websocketonerror(e){
            console.error('ws 連線失敗',e);
        },
        websocketonmessage(e){
            // 後端通知前端,前端取得資料
            let _data = e.data;
            //當有後端資料送到前端,利用vuex存到共用的state
            this.setWsNotify({
                id:uuid.v4(), 
                data: JSON.parse(_data)
            });
            console.log('ws 取得資料',_data);
        },
        websocketsend(data){
            //前端丟資料
            console.log('send data',data);
        },
        websocketclose(){
            console.log('ws 關閉連線')
        }
    }
}

2-3. 選擇連通websocket通道的時機 - 全站入口點

這邊我自己曾經考慮過在某些特定的頁面進入後再開啟,但這樣就會變成來回進入頁面會開關通道頻繁,因此我最後決定進到網站的時候,就將websocket通道開啟,進到網站後,只進行一次handshake,就保持連線。
因此,在App.vue (全站入口),加入通道開啟及關閉的方法。

import { mixinWebsocket } from '@/utils/ws';
export default {
    mixins: [mixinWebsocket],
    created(){
        this.initWebsocket(); //開啓前後端的websocket通道
    },
    destroy(){
        this.websocketclose(); //關閉websocket通道
    }
}

2-4. 在需要的頁面watch vuex中state的WsNotify,從前端送資料或後端送資料給前端

import { mixinWebsocket } from '@/utils/ws';
export default {
    mixins: [mixinWebsocket],
    watch:{
        wsNotify:{
            handler(val){
                let {id, data} = val;
                // 根據data決定要do something
            },
            deep:true
        }
        
    },
    
}

以上大概是我的vue環境建立websocket流程,主要著重在後端通知前端,當然有些情況也是前端要告知後端。那就使用前面提到的websocketsend()傳送資料就可以囉。
也很歡迎大家分享一下在vue.js中實作websocket的方法,也許有其他的寫法更好,快來一起討論吧~~


上一篇
DAY 09 - 由後端主動告訴你資料更新 - websocket
下一篇
DAY11 - 前端網頁怎麼處理檔案?
系列文
不只是串串API,新手前端30天30

尚未有邦友留言

立即登入留言