This is the second day of my participation in Gwen Challenge

Remax has been used for a long time, previously using javascript versions

In June, the project was ready for Typescript refactoring, so we rethought a version

A little knowledge

Wx. connectSocket of wechat applet can only make a maximum of two requests to a WS/WSS websocket at the same time, and can use a maximum of 5 connections for multiple different Websocket addresses.

Wechat SocketTask is a SocketTask object that can be returned after a connectSocket is used to establish a connection. You can store this connection internally. It is not recommended because websocket connections are likely to be lost when the page is refreshed. Using localstroage to cache the socket is not available. Therefore, it is recommended to instantiate each time a new WebSocket connection is used. Then pass in the corresponding WS/WSS connection for linking operation.

Wx.connectsocket -> wx.onSocketOpen -> wx.onReceivedMsg -> Wx.onReceivedMsg -> Wx.onSocketOpen -> Wx.onReceivedMsg -> wx.sendSocketMessage

So when you cannot send or receive data from the server and push data to the server, you should check the execution timing.


filename: src/utils/websocket.ts

import {
    connectSocket,
    closeSocket,
    onSocketOpen,
    onSocketClose,
    sendSocketMessage,
    onSocketMessage,
    getNetworkType,
    onNetworkStatusChange,
} from 'remax/wechat';

class Websocket {
    // Whether to connect
    isConnect: boolean = false;
    // Current network status
    private netWork: boolean = false;
    // Whether to exit manually
    private isClosed: boolean = false;
    // Heartbeat detection frequency
    private timeout: number = 3 * 1000;
    private timeoutObj: NodeJS.Timeout | undefined;
    // Number of current reconnections
    private connectNum: number = 0;
    // Heartbeat detection and disconnection reconnection switch. The value can be true or false
    heartCheck: boolean = false
    isReconnect: boolean = false
    // Connection information
    wsUrl = ' '
    // Message queue
    messageQueue = []

    constructor(heartCheck: boolean = false, isReconnect: boolean = false) {
        // Heartbeat detection and disconnection reconnection switch. The value can be true or false
        this.heartCheck = heartCheck;
        this.isReconnect = isReconnect;
    }

    // The heartbeat starts
    start() {
        const self = this;
        this.timeoutObj = setInterval(() = > {
            sendSocketMessage({
                // Send heartbeat message
                data: JSON.stringify({
                    beat: 'dj',}).success() {
                    // console.log(" Heartbeat sent successfully ");
                },
                fail(err) {
                    console.log(err);
                    console.log('Connection failed');
                    self.reConnect()
                    self.reset();
                },
            }).then();
        }, this.timeout);
    }

    // Heartbeat reset
    reset() {
        if (this.timeoutObj) {
            clearTimeout(this.timeoutObj);
        }
        // Return this to support chained calls
        return this;
    }

    // Initialize the connection
    init(wsUrl: string) {
        if (this.isConnect) {
            this.onSocketOpened()
            this.onNetworkChange()
            this.onSocketClosed()
        } else {
            // Check network status
            const self = this;
            getNetworkType({
                success(res) {
                    if(res.networkType ! = ='none') {
                        // Start establishing a connection
                        console.log('Start connection')
                        self.connect(wsUrl)
                    } else {
                        self.netWork = false;
                        console.log('Network disconnected'); } }, }).then(); }}/ / the websocket connection
    connect(wsUrl: string) {
        // connectSocket does not support asynchronous calls
        let self = this;
        connectSocket({
            url: wsUrl,
            success(res) {
                if (res.errMsg == 'connectSocket:ok') {
                    self.isConnect = true
                    self.wsUrl = wsUrl
                    self.onSocketOpened()
                    self.onNetworkChange()
                    self.onSocketClosed()
                }
            },
            fail(err) {
                console.log(err)
            },
        });
    }

    // The reconnection method will be slower and slower depending on the time frequency, respectively 3 seconds, 10 seconds, 45 seconds
    reConnect() {
        console.log(this.connectNum)
        if (!this.isConnect) {
            if (this.connectNum < 3) {
                setTimeout(() = > {
                    this.init(this.wsUrl);
                }, 3 * 1000);
                this.connectNum += 1;
            } else if (this.connectNum < 10) {
                setTimeout(() = > {
                    this.init(this.wsUrl);
                }, 10 * 1000);
                this.connectNum += 1;
            } else {
                setTimeout(() = > {
                    this.init(this.wsUrl);
                }, 45 * 1000);
                this.connectNum += 1; }}}// Close the webSocket connection
    close() {
        if (this.isConnect) {
            closeSocket().then()
            // Reset the heartbeat and change the corresponding state
            this.reset()
            this.isClosed = true;
            this.isConnect = false;
        } else {
            console.warn('No Websocket connection')}}// The webSocket connection is closed
    onSocketClosed() {
        onSocketClose((err) = > {
            console.log('The current WebSocket connection is closed with the following error message:The ${JSON.stringify(err)}`);
            // Stop the heartbeat connection
            if (this.heartCheck) {
                this.reset();
            }
            // Turn off the logon switch
            this.isConnect = false;
            // Check if the user exits the applet
            if (!this.isClosed) {
                console.log('Came in here... ')
                // Reconnection
                if (this.isReconnect) {
                    this.reConnect(); }}}); }// Check network changes
    onNetworkChange() {
        let self = this;
        onNetworkStatusChange((res) = > {
            if (res.isConnected) {
                self.isConnect = false;
                self.reConnect()
            }
        });
    }

    // The socket is enabled
    onSocketOpened() {
        onSocketOpen(() = > {
            console.log('Websocket open');
            // Turn on the connected switch
            this.isConnect = true;
            this.netWork = true;
            // Send heartbeat
            if (this.heartCheck) {
                this.reset().start(); }}); }// Receive the message returned by the server
    onReceivedMsg(callBack: any) {
        onSocketMessage((msg) = > {
            if (typeof callBack === 'function') { callBack(msg); }}); }// Send the WS message
    sendWebSocketMsg(options: any) {
        sendSocketMessage({
            data: options.data,
            success(res) {
                if (options.success && typeof options.success === 'function') { options.success(res); }},fail(err) {
                if (options.fail && typeof options.fail === 'function') { options.fail(err); } }, }).then(); }}const websocket = new Websocket(
    // true indicates that heartbeat detection and disconnection are enabled
    true.true,);export default websocket;
Copy the code

How do you use it?

filename: src/page/index.tsx

import * as React from 'react';
import {View, Text, Image, Button} from 'remax/wechat';
import styles from './index.css';
import websocket from "@/utils/wxsocket";

export default() = > {const connectWs = () = > {
        const wsUrl = 'ws:// Test or online WS address information using WSS ://' if HTTPS encryption
        if(! websocket.isConnect) { websocket.init(wsUrl) } }const closeWs = () = > {
        if (websocket.isConnect) {
            websocket.close()
        }
    }
    return (
        <View className={styles.app}>
            <View className={styles.header}>
                <Image
                    src="https://gw.alipayobjects.com/mdn/rms_b5fcc5/afts/img/A*OGyZSI087zkAAAAAAAAAAABkARQnAQ"
                    className={styles.logo}
                />
                <Button onClick={()= >ConnectWs ()}> Start connecting to the WS server</Button>
                <Button onClick={()= >CloseWs ()}> Close the WS connection server</Button>
            </View>
        </View>
    );
};

Copy the code

After the connectionAfter closing the link