In the process of using websocket, sometimes the network is disconnected, but the server does not trigger the onClose event when the network is disconnected. The server will continue to send redundant links to the client, and the data will be lost. Therefore, a mechanism is needed to detect whether the client and server are properly connected. Hence the websocket heartbeat. There’s a heartbeat, which means you’re alive, and no heartbeat means you’re dead.
1. Why is it called a heartbeat bag?
It’s like a heartbeat at regular intervals, telling the server THAT I’m still alive.
2. What is the heartbeat mechanism?
The heartbeat mechanism is a mechanism that periodically sends a custom structure (heartbeat packet) to let the other party know that they are alive and ensure the validity of the connection.
Implementation method? The following code:
class wsRequest {
constructor(url, time) {
this.status = null; // Whether webSocket is closed
this.lockReconnect = false // Avoid duplicate connections
this.url = url
// Heartbeat detection
this.timeout= time // How many seconds to execute the test
this.timeoutObj= null // Check whether the server is still alive
this.reconnectTimeOutObj= null // How long after reconnection to reconnect again
try {
return this.initRequest()
} catch (e) {
console.log('catch');
this.reconnect(); }}initRequest() {
this.socketTask = uni.connectSocket({
url: this.url, // Interface address.
success: () = > {
console.log('Connection successful');
// Return the instance
return this.socketTask
}
})
this.socketTask.onOpen(res= > {
console.log(res, 'Connection open');
// Clear the reconnection timer
clearTimeout(this.reconnectTimeOutObj)
// Enable detection
this.start()
})
// Bind the reconnection method on close or error if you want the WebSocket connection to last forever.
this.socketTask.onClose((res) = > {
console.log(res, 'Connection closed');
this.reconnect();
})
this.socketTask.onError((res) = > {
console.log(res, 'Connection error');
this.reconnect();
})
this.socketTask.onMessage(res= > {
// Accepting any message indicates that the current connection is normal
this.reset();
console.log(res, 'pong'); })}send(value) {
return new Promise((resovle,reject) = >{
this.socketTask.send({
data: value,
success:() = >{
resovle('Sent successfully')}})})}// The reset and start methods are used to control the timing of the heartbeat.
reset(){
// Clear the timer and re-send a heartbeat message
clearTimeout(this.timeoutObj);this.start();
}
start(){
this.timeoutObj = setTimeout(() = > {
// A heartbeat message is sent, and the back end returns a heartbeat message,
// if onMessage receives the returned heartbeat, the connection is normal
console.log('ping');
this.socketTask.send({data:"ping"});
}, this.timeout)
}
/ / reconnection
reconnect() {
// Prevent multiple method calls, multiple reconnections
if (this.lockReconnect) {
return;
};
this.lockReconnect = true;
console.log('Ready for reconnection');
// Set delay to avoid too many requests
this.reconnectTimeOutObj = setTimeout(() = >{
// Reconnect
this.initRequest()
this.lockReconnect = false;
}, 4000);
}
// Manually close
close() {
this.socketTask.close()
}
}
module.exports = wsRequest
Copy the code
The specific ideas are as follows:
1. Create a wsRequest class to initialize the constructor data
class wsRequest {
constructor(url, time) {
this.status = null; // Whether webSocket is closed
this.lockReconnect = false // Avoid duplicate connections
this.url = url
// Heartbeat detection
this.timeout= time // How many seconds to execute the test
this.timeoutObj= null // Check whether the server is still alive
this.reconnectTimeOutObj= null // How long after reconnection to reconnect again
try {
return this.initRequest()
} catch (e) {
console.log('catch');
this.reconnect(); }}}Copy the code
2. The second step is to use initRequest, which calls the websocket API of uni-App:
initRequest() {
this.socketTask = uni.connectSocket({
url: this.url, // Interface address.
success: () = > {
console.log('Connection successful');
// Return the instance
return this.socketTask
}
})
this.socketTask.onOpen(res= > {
console.log(res, 'Connection open');
})
this.socketTask.onClose((res) = > {
console.log(res, 'Connection closed');
})
this.socketTask.onError((res) = > {
console.log(res, 'Connection error');
})
this.socketTask.onMessage(res= > {
console.log(res); })}Copy the code
2.1 Send Sends events
send(value) {
// This return is optional
//return new Promise((resovle,reject)=>{
this.socketTask.send({
data: value,
success:() = >{
resovle('Sent successfully')}})/ /})
}
Copy the code
3. Reconnect code is as follows:
reconnect() {
// Prevent multiple method calls (onError/onError will be called), multiple reconnections
if (this.lockReconnect) {
return;
};
this.lockReconnect = true;
console.log('Ready for reconnection');
// Set delay to avoid too many requests
this.reconnectTimeOutObj = setTimeout(() = >{
// Reconnect
this.initRequest()
this.lockReconnect = false;
}, 5000);
}
Copy the code
Call reconnect in the onClose,onError listener event
4. Detect heartbeat and send heartbeat packets
reset(){
// Clear the timer and re-send a heartbeat message
clearTimeout(this.timeoutObj);this.start();
}
start(){
this.timeoutObj = setTimeout(() = > {
// A heartbeat message is sent, and the back end returns a heartbeat message,
// if onMessage receives the returned heartbeat, the connection is normal
console.log('ping');
this.socketTask.send({data:"ping"});
}, this.timeout)
}
Copy the code
Enable detection when the onOpen link is opened and reset the timer when the onMessage listener receives a message
this.socketTask.onOpen(res= > {
console.log(res, 'Connection open');
// Clear the reconnection timer
clearTimeout(this.reconnectTimeOutObj)
// Enable detection
this.start()
})
this.socketTask.onMessage(res= > {
// Accepting any message indicates that the current connection is normal
this.reset();
console.log(res, 'pong');
})
Copy the code
The idea of heartbeat detection is as follows: Fixed time intervals and send a ping to a server-side data, if in normal circumstances, the server will return a pong to the client, if the client through the onMessage event can listen to the words, that request is normal, here using a timer, under the condition of every 5 seconds, if it is under the condition of network disconnection, The server does not return a heartbeat response message within the specified time, so the server is disconnected, so this time is heard through the onClose event. So inside the onClose event, we can call the Reconnect event to do the reconnect.