• 微信小程序使用原生WebSokcet实现断线重连及数据拼接


    以前做小程序为了应急找了个插件去链接WebSokcet,文章传送门

    回过头在新项目中再次使用时出现了些许问题,不一一赘述。遂决定好好用一下原生的WebSokcet。

    一、说明

    1.小程序原生的WebSokcet没有断线重连机制,这个是他的不足之处。

    2.小程序新的版本库已经支持存在多个 WebSokcet 连接。

      官方说明:基础库 1.7.0 之前,一个微信小程序同时只能有一个 WebSocket 连接,如果当前已存在一个 WebSocket 连接,会自动关闭该连接,并重新创建一个 WebSocket 连接。基础库版本 1.7.0 及以后,支持存在多个 WebSokcet 连接,每次成功调用 wx.connectSocket 会返回一个新的 SocketTask

    官方文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-socket.html#wxclosesocket

    二、实际例子:

    首先你需要socket地址url: let url = 'wss://xxx.xxx.com/?xxx=xxx'

    注意:1.小程序管理后台添加socket域名的时候不能出现端口;2.如果使用了appID,协议必须是 wss;3.socket服务端映射的端口仅支持 80 和 443,和公众号一个尿性。

    接下来放例子:

    1、socket.js

    const app = getApp();
    let url = 'wss://xxx.xxx.com/?xxx=xxx'
    export const connect = function (cb) {  // 定义一个方法
        wx.connectSocket({ // 创建一个 WebSocket 连接
            url: url,
            fail (err) {
                if (err) {
                    console.log('%cWebSocket连接失败', 'color:red', err)
                    app.globalData.socketConnectFail = true // 定义一个全局变量,当链接失败时改变变量的值
                }
            }
        })
    
        wx.onSocketOpen(function (res) { // 监听WebSocket连接打开事件。
            console.log('WebSocket打开成功');
            wx.sendSocketMessage({ // 通过 WebSocket 连接发送数据,需要先 wx.connectSocket,并在 wx.onSocketOpen 回调之后才能发送。
                data: Buffer2Base64(), // 用于订阅的参数,视具体情况而定
                success (data) {
                    console.log('WebSocket发送消息:', data.errMsg)
                },
                fail (err) {
                    console.log('Err', err)
                }
            })
    
        })
    
        wx.onSocketMessage(function (res) { // 监听WebSocket接受到服务器的消息事件。
            console.log('WebSocket接收到消息:', ArryBuffer2Json(res.data));
            cb(ArryBuffer2Json(res.data)); // 将接收到的消息进行回调,如果是ArryBuffer,需要进行转换
        })
    
        wx.onSocketError(function (res) { // 监听WebSocket错误。
            console.log('WebSocket连接打开失败')
        })
    
        wx.onSocketClose(function (res) { // 监听WebSocket关闭。
            console.log('WebSocket关闭');
        })
    };
    function ArryBuffer2Json (data) { // ArryBuffer转换成Json
        try {
            var Base64String = String.fromCharCode.apply(null, new Uint8Array(data));
            var Base64JsonStr = decodeURIComponent(base64_decode(Base64String));
            return JSON.parse(Base64JsonStr);
        } catch (err) {
            console.log(err);
            return false;
        }
    }
    
    function Buffer2Base64 () { // 用于订阅的参数,视具体情况而定
        var packet = {};
        packet["cmd"] = "subscribe";
        packet["reqNo"] = "" + new Date().getTime();
        packet["params"] = {token: token, channelId: 'xcx', columnIds: "1"};
        return stringToBuffer(JSON.stringify(packet))
    }
    
    function stringToBuffer (string) {
        var string = base64_encode(encodeURIComponent(string)),
            charList = string.split(''),
            uintArray = [];
        for (var i = 0; i < charList.length; i++) {
            uintArray.push(charList[i].charCodeAt(0));
        }
        return new Uint8Array(uintArray).buffer;
    }
    
    function base64_encode (str) { // base64编码
        var c1, c2, c3;
        var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        var i = 0, len = str.length, string = '';
    
        while (i < len) {
            c1 = str.charCodeAt(i++) & 0xff;
            if (i == len) {
                string += base64EncodeChars.charAt(c1 >> 2);
                string += base64EncodeChars.charAt((c1 & 0x3) << 4);
                string += "==";
                break;
            }
            c2 = str.charCodeAt(i++);
            if (i == len) {
                string += base64EncodeChars.charAt(c1 >> 2);
                string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
                string += base64EncodeChars.charAt((c2 & 0xF) << 2);
                string += "=";
                break;
            }
            c3 = str.charCodeAt(i++);
            string += base64EncodeChars.charAt(c1 >> 2);
            string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            string += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
            string += base64EncodeChars.charAt(c3 & 0x3F)
        }
        return string
    }

    function base64_decode (input) { // base64解码
    var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;
    input = input.replace(/[^A-Za-z0-9+/=]/g, "");
    while (i < input.length) {
    enc1 = base64EncodeChars.indexOf(input.charAt(i++));
    enc2 = base64EncodeChars.indexOf(input.charAt(i++));
    enc3 = base64EncodeChars.indexOf(input.charAt(i++));
    enc4 = base64EncodeChars.indexOf(input.charAt(i++));
    chr1 = (enc1 << 2) | (enc2 >> 4);
    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
    chr3 = ((enc3 & 3) << 6) | enc4;
    output = output + String.fromCharCode(chr1);
    if (enc3 != 64) {
    output = output + String.fromCharCode(chr2);
    }
    if (enc4 != 64) {
    output = output + String.fromCharCode(chr3);
    }
    }
    return utf8_decode(output);
    }

    function utf8_decode (utftext) { // utf-8解码
    var string = '';
    let i = 0;
    let c = 0;
    let c1 = 0;
    let c2 = 0;
    while (i < utftext.length) {
    c = utftext.charCodeAt(i);
    if (c < 128) {
    string += String.fromCharCode(c);
    i++;
    } else if ((c > 191) && (c < 224)) {
    c1 = utftext.charCodeAt(i + 1);
    string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
    i += 2;
    } else {
    c1 = utftext.charCodeAt(i + 1);
    c2 = utftext.charCodeAt(i + 2);
    string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
    i += 3;
    }
    }
    return string;
    }

    2、index.js
    let openSocket = require('../../config/socket.js');
    const app = getApp();
    
    data: {
        motto: 'Hello World',
        articleData: []
    },
    onLoad: function () {
        let that = this;
        openSocket.connect(function (data) { // WebSocket初始化连接
            let result = data.data
            if (result) {
                that.setData({articleData: [result].concat(that.data.articleData)}) // 将获得的socket推送消息拼接到当前文章列表的最前面
            }
        });
        if (app.globalData.socketConnectFail) { // WebSocket断线重连
            setInterval(() => {
                openSocket.connect(function (data) {
                    let result = data.data
                    if (result) {
                        that.setData({articleData: [result].concat(that.data.articleData)})
                    }
                });
            }, 1000)
        }
    }
    3、app.js
    
    globalData: {
        socketConnectFail: false
    }
     
  • 相关阅读:
    手机端网页web开发要点
    js javascript:void(0) 真正含义
    牛客第二场 C.message(计算几何+二分)
    计算几何_三维凸包
    【kuangbin专题】计算几何_半平面交
    【kuangbin专题】计算几何_凸包
    【kuangbin专题】计算几何基础
    Codeforces 1058 D. Vasya and Triangle(分解因子)
    网络流模板
    2018 Multi-University Training Contest 6
  • 原文地址:https://www.cnblogs.com/Man-Dream-Necessary/p/8351850.html
Copyright © 2020-2023  润新知