1、在react中使用websocket
在项目根目录中创建一个websocket文件夹用于封装公用组件
代码如下:
/**
* 参数:[socketOpen|socketClose|socketMessage|socketError] = func,[socket连接成功时触发|连接关闭|发送消息|连接错误]
* timeout:连接超时时间
* @type {module.webSocket}
*/
class webSocket {
constructor(param = {}) {
this.param = param;
this.reconnectCount = 0;
this.socket = null;
this.taskRemindInterval = null;
this.isSucces=true;
}
connection = () => {
let {socketUrl, timeout = 0} = this.param;
// 检测当前浏览器是什么浏览器来决定用什么socket
if ('WebSocket' in window) {
console.log('WebSocket');
this.socket = new WebSocket(socketUrl);
}
else if ('MozWebSocket' in window) {
console.log('MozWebSocket');
// this.socket = new MozWebSocket(socketUrl);
}
else {
console.log('SockJS');
// this.socket = new SockJS(socketUrl);
}
this.socket.onopen = this.onopen;
this.socket.onmessage = this.onmessage;
this.socket.onclose = this.onclose;
this.socket.onerror = this.onerror;
this.socket.sendMessage = this.sendMessage;
this.socket.closeSocket = this.closeSocket;
// 检测返回的状态码 如果socket.readyState不等于1则连接失败,关闭连接
if(timeout) {
let time = setTimeout(() => {
if(this.socket && this.socket.readyState !== 1) {
this.socket.close();
}
clearInterval(time);
}, timeout);
}
};
// 连接成功触发
onopen = () => {
let {socketOpen} = this.param;
this.isSucces=false //连接成功将标识符改为false
socketOpen && socketOpen();
};
// 后端向前端推得数据
onmessage = (msg) => {
let {socketMessage} = this.param;
socketMessage && socketMessage(msg);
// 打印出后端推得数据
console.log(msg);
};
// 关闭连接触发
onclose = (e) => {
this.isSucces=true //关闭将标识符改为true
console.log('关闭socket收到的数据');
let {socketClose} = this.param;
socketClose && socketClose(e);
// 根据后端返回的状态码做操作
// 我的项目是当前页面打开两个或者以上,就把当前以打开的socket关闭
// 否则就20秒重连一次,直到重连成功为止
if(e.code=='4500'){
this.socket.close();
}else{
this.taskRemindInterval = setInterval(()=>{
if(this.isSucces){
this.connection();
}else{
clearInterval(this.taskRemindInterval)
}
},20000)
}
};
onerror = (e) => {
// socket连接报错触发
let {socketError} = this.param;
this.socket = null;
socketError && socketError(e);
};
sendMessage = (value) => {
// 向后端发送数据
if(this.socket) {
this.socket.send(JSON.stringify(value));
}
};
};
export {
webSocket,
}
这样就完成了websocket的全局功能组件封装,在需要用的组件进行引用就行了
例:
import {webSocket} from "../../WebSocket/index";
//函数调用
WebSocketTest=()=>{
// 判断专家是否登录
let that = this;
let userId = JSON.parse(localStorage.getItem("adminInfo")).id;
console.log(userId)
this.socket = new webSocket({
socketUrl: 'ws://xx.xxx.xxx/imserver/'+userId,
timeout: 5000,
socketMessage: (receive) => {
console.log(receive)
// if(receive.data === '1'){
// console.log(receive); //后端返回的数据,渲染页面
// }else if(JSON.parse(receive.data)){
// that.setState({msgData:receive.data})
// }else{
// message.info("有新消息了")
// }
try {
if (typeof JSON.parse(receive.data) == "object") {
that.setState({msgData:receive.data})
}else if(receive.data === '1'){
console.log(receive.data);
}
} catch(e) {
message.info(receive.data)
}
},
socketClose: (msg) => {
console.log(msg);
},
socketError: () => {
console.log(this.state.taskStage + '连接建立失败');
message.error("消息通信连接失败,建议刷新")
},
socketOpen: () => {
console.log('连接建立成功');
// 心跳机制 定时向后端发数据
this.taskRemindInterval = setInterval(() => {
this.socket.sendMessage({ "msgType": 0 })
}, 30000)
}
});
//重试创建socket连接
try {
this.socket.connection();
} catch (e) {
// 捕获异常,防止js error
// donothing
}
}
2、websocket在小程序中使用
小程序官方文档里是有相关的组件和调用方法,所以这里就不详细介绍了,简单说一下我的理解和使用方法。
在项目根目录下创建websocket文件
const app = getApp();
import { webSocketUrl } from '../utils/requst/url';
//websocket封装模块
const lqoWS = {
openSocket(val) {
let wsData = app.globalData.wsData;
//我这里向后端传参用的路径参数,所以这里稍微设置一下
let urls = ''
if(val == '/userSocket/'){
urls = webSocketUrl + val + wsData.id
}
if(val == '/ownerSocket/'){
urls = webSocketUrl + val + wsData.id + '/' + wsData.lon + '/' + wsData.lat;
}
//打开时的动作
wx.onSocketOpen(() => {
console.log('WebSocket 已连接')
app.globalData.socketStatus = 'connected';
this.sendMessage(val);
})
//断开时的动作
wx.onSocketClose(() => {
console.log('WebSocket 已断开')
if(app.globalData.socketStatus == 'closeds'){
return
}
app.globalData.socketStatus = 'closed';
this.pdSocketOpen(val);
})
//报错时的动作
wx.onSocketError(error => {
console.error('socket error:', error)
})
// 监听服务器推送的消息
wx.onSocketMessage(message => {
//把JSONStr转为JSON
message = message.data.replace(" ", "");
if (typeof message != 'object') {
message = message.replace(/\ufeff/g, ""); //重点
var jj = JSON.parse(message);
message = jj;
}
console.log(message)
})
// 打开信道
wx.connectSocket({
url: urls,
success:(res)=>{
console.log(res)
}
})
},
//关闭信道
closeSocket(val) {
if (app.globalData.socketStatus == 'connected') {
wx.closeSocket({
success: () => {
app.globalData.socketStatus = 'closeds'
}
})
}
},
//发送消息函数
sendMessage(val) {
if (app.globalData.socketStatus == 'connected') {
//自定义的发给后台识别的参数 ,我这里发送的是name
wx.sendSocketMessage({
// data: "{\"name\":\"" + '123' + "\"}"
data: app.globalData.wsData
})
}
},
pdSocketOpen (val) {
setTimeout(() => {
if(app.globalData.socketStatus == 'closed'){
// console.log(app.globalData.socketStatus)
this.openSocket(val);
}
}, 4000)
},
}
export {
lqoWS,
}
使用
代码里的相关参数需要在全局中进行设置
import { lqoWS } from '../../websoket/index';
let val = '/ownerSocket/';
if(app.globalData.socketStatus == 'closed'){
// that.openSocket();
lqoWS.openSocket(val);
}
// lqoWS.closeSocket(val);
lqoWS.sendMessage(val);
lqoWS.pdSocketOpen(val);
小程序官方有非常详细的使用说明。