uniapp連接websocket報錯?


論壇問題: https://ask.dcloud.net.cn/question/74505

使用: uni.connectSocket(OBJECT) 和  SocketTask.onOpen(CALLBACK) 在安卓手機無法觸發websocket的open方法

解決辦法使用plus-websocket插件

https://ext.dcloud.net.cn/plugin?id=647

注意方法使用:

socket.connectSocket(OBJECT)

  • socket.onSocketOpen(CALLBACK)
  • socket.onSocketError(CALLBACK)
  • socket.sendSocketMessage(OBJECT)
  • socket.onSocketMessage(CALLBACK)
  • socket.closeSocket(OBJECT)
  • socket.onSocketClose(CALLBACK)

轉載大佬的插件案例: https://www.jianshu.com/p/241fd3a81c3f

/**uni websocket工具類*/
//npm i plus-websocket --save
import socket from 'plus-websocket'
export default class websocket {
    constructor({
        heartCheck,
        isReconnection
    }) {
        // 是否連接
        this._isLogin = false;
        // 當前網絡狀態
        this._netWork = true;
        // 是否人為退出
        this._isClosed = false;
        // 心跳檢測頻率
        this._timeout = 3000;
        this._timeoutObj = null;
        // 當前重連次數
        this._connectNum = 0;
        // 心跳檢測和斷線重連開關,true為啟用,false為關閉
        this._heartCheck = heartCheck;
        this._isReconnection = isReconnection;
        // this._onSocketOpened();
    }
    // 心跳重置
    _reset() {
        clearTimeout(this._timeoutObj);
        return this;
    }
    // 心跳開始
    _start() {
        let _this = this;
        this._timeoutObj = setInterval(() => {
            //發送心跳
            _this.sendHeartbeatData();
        }, this._timeout);
    }
    // 監聽websocket連接關閉
    onSocketClosed(options) {
        socket.onSocketClose(err => {
            console.log('當前websocket連接已關閉,錯誤信息為:' + JSON.stringify(err));
            // 停止心跳連接
            if (this._heartCheck) {
                this._reset();
            }
            // 關閉已登錄開關
            this._isLogin = false;
            // 檢測是否是用戶自己退出小程序
            if (!this._isClosed) {
                // 進行重連
                if (this._isReconnection) {
                    this._reConnect(options)
                }
            }

        })
    }
    // 檢測網絡變化
    onNetworkChange(options) {

        uni.onNetworkStatusChange(res => {
            console.log('當前網絡狀態:' + res.isConnected);
            if (!this._netWork) {
                this._isLogin = false;
                // 進行重連
                if (this._isReconnection) {
                    this._reConnect(options)
                }
            }
        })
    }
    _onSocketOpened() {
        socket.onSocketOpen(res => {
            console.log('【websocket】已打開');
            // 打開已登錄開關
            this._isLogin = true;
            // 發送心跳
            if (this._heartCheck) {
                this._reset()._start();
            }
            // 發送登錄信息
            this.sendLoginData();
            // 打開網絡開關
            this._netWork = true;
        })
    }
    // 接收服務器返回的消息
    onReceivedMsg(callBack) {
        socket.onSocketMessage(event => {
            let msg = this.socketEventDataToStr(event)
            // console.log(msg);
            if (typeof callBack == "function") {
                callBack(msg)
            } else {
                console.log('參數的類型必須為函數')
            }
        })
    }

    // 建立websocket連接
    initWebSocket(options) {

        let _this = this;
        if (this._isLogin) {
            console.log("您已經登錄了");
        } else {
            // 檢查網絡
            uni.getNetworkType({
                success(result) {
                    if (result.networkType != 'none') {
                        // 開始建立連接
                        console.log('建立websocket連接' + options.url);
                        socket.connectSocket({
                            url: options.url,
                            success(res) {
                                if (typeof options.success == "function") {
                                    options.success(res)
                                    _this._onSocketOpened();
                                } else {
                                    console.log('參數的類型必須為函數')
                                }
                            },
                            fail(err) {
                                if (typeof options.fail == "function") {
                                    options.fail(err)
                                } else {
                                    console.log('參數的類型必須為函數')
                                }
                            }
                        })
                    } else {
                        console.log('網絡已斷開');
                        _this._netWork = false;
                        // 網絡斷開后顯示model
                        uni.showModal({
                            title: '網絡錯誤',
                            content: '請重新打開網絡',
                            showCancel: false,
                            success: function(res) {
                                if (res.confirm) {
                                    console.log('用戶點擊確定')
                                }
                            }
                        })
                    }
                }
            })
        }
    }
    // 發送websocket消息
    sendWebSocketMsg(options) {
        this.sendBinary(1,options);
    }

    //發送心跳連接
    sendHeartbeatData() {
        this.sendBinary(99, {
            data: {},
            success(res) {
                console.log('【websocket】心跳連接成功')
            },
            fail(err) {
                console.log('【websocket】心跳連接失敗')
                console.log(err)
            }
        });
    }

    //發送第一次連接數據
    sendLoginData() {
        this.sendBinary(99, {
            data: {},
            success(res) {
                console.log('【websocket】第一次連接成功')
            },
            fail(err) {
                console.log('【websocket】第一次連接失敗')
                console.log(err)
            }
        });
        // this.sendBinary(99, {});
        // socket.sendSocketMessage({
        //  // 這里是第一次建立連接所發送的信息,應由前后端商量后決定
        //  data: JSON.stringify({
        //      "key": 'value'
        //  })
        // })
    }

    // 重連方法,會根據時間頻率越來越慢
    _reConnect(options) {
        let timer, _this = this;
        if (this._connectNum < 20) {
            timer = setTimeout(() => {
                this.initWebSocket(options)
            }, 3000)
            this._connectNum += 1;
        } else if (this._connectNum < 50) {
            timer = setTimeout(() => {
                this.initWebSocket(options)
            }, 10000)
            this._connectNum += 1;
        } else {
            timer = setTimeout(() => {
                this.initWebSocket(options)
            }, 450000)
            this._connectNum += 1;
        }
    }
    // 關閉websocket連接
    closeWebSocket() {
        socket.closeSocket();
        this._isClosed = true;
    }

    //發送二進制
    sendBinary(commendType, options) {
        let sendMsg = options.data
        let uint8Array = new TextEncoder().encode(JSON.stringify(sendMsg));
        let byteArr = new ArrayBuffer(4 + uint8Array.length);
        //DataView有三個參數,后兩個可以缺省;每一個要是ArrayBuffer對象或SharedArrayBuffer對象
        let dv = new DataView(byteArr);
        dv.setUint32(0, commendType, false);
        for (let i = 0; i < uint8Array.length; i++) {
            dv.setUint8(4 + i, uint8Array[i]);
        }
        // console.log(dv);
        socket.sendSocketMessage({
            data: dv.buffer,
            success(res) {

                if (typeof options.success == "function") {
                    options.success(res)
                } else {
                    console.log('參數的類型必須為函數')
                }
            },
            fail(err) {
                if (typeof options.fail == "function") {
                    options.fail(err)
                } else {
                    console.log('參數的類型必須為函數')
                }
            }
        });
    }

    //轉化方法
    socketEventDataToStr(event) {
        let dv = new DataView(event.data);
        let commendType = dv.getUint32(0, true);
        let slice = event.data.slice(4, event.data.length);
        let unit8Arr = new Uint8Array(slice);
        let s = new TextDecoder("utf-8").decode(unit8Arr);
        console.log("【websocket】標志位:" + commendType);
        console.log("【websocket】返回信息:" + s);
        return s;
    }

}
轉載簡書大佬的案例

 


免責聲明!

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



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