vue3中实现websocket
方式1 websocket 在vuex中实现
import { createStore } from 'vuex'
import { socket } from '@/types/vuex'
import storage from 'store'
const state: socket = {
//推送消息
data: {},
webSocket: null,
timer: null,
hearbeat_interval: 1000 * 2
}
const store = createStore({
state,
getters: {
getData: state => state.data
},
mutations: {
initWebsocket(state) {
state.webSocket = new WebSocket(
'ws://localhost:8000'
)
state.webSocket.onopen = function () {
console.log('通讯开始')
state.timer && clearInterval(state.timer)
state.timer = setInterval(() => {
state.webSocket.send(JSON.stringify({
// token: storage.get('token')
token: Math.random()
}))
}, state.hearbeat_interval)
}
state.webSocket.onmessage = function (e: { data: string | Object }) {
console.log('收到的数据:', e.data)
let data = JSON.parse(e.data as string)
state.data = e.data
// console.log(data)
}
state.webSocket.onerror = function () {
console.log('通讯异常')
}
state.webSocket.onclose = function () {
console.log('连接已断开')
state.timer && clearInterval(state.timer)
}
},
},
actions: {
},
modules: {
}
})
export default store;
// 在组件中使用
import {
ref,
defineComponent,
watch,
} from 'vue'
import { useStore } from 'vuex'
export default defineComponent({
setup(){
const store = useStore()
const initSocket = () => {
store.commit('initWebsocket')
}
onBeforeMount(() => {
initSocket()
console.log('store', store)
})
onUnmounted(() => {
// ws.close()
store.state.webSocket.close()
})
const data = ref('')
watch(
() => store.getters.getData,
(newValue, oldValue) => {
data.value = newValue
console.log('watch 已触发', newValue)
}
)
return { data }
}
})
@/types/vuex/index.ts中定义一个接口
export interface socket {
webSocket: any
data: Object
[propName: string]: any
}
方式2 websocket 在utils中单独封装
import { ElMessage as message } from 'element-plus'
import storage from 'store'
import socket from '@/types/api/socket'
const socket: socket = {
websocket: null,
connectURL: 'ws://localhost:8000',
// 开启标识
socket_open: false,
// 心跳timer
hearbeat_timer: null,
// 心跳发送频率
hearbeat_interval: 2 * 1000,
// 是否自动重连
is_reonnect: true,
// 重连次数
reconnect_count: 3,
// 已发起重连次数
reconnect_current: 1,
// 重连timer
reconnect_timer: null,
// 重连频率
reconnect_interval: 5 * 1000,
init: (receiveMessage: Function | null) => {
if (!('WebSocket' in window)) {
message.warning('浏览器不支持WebSocket')
return null
}
socket.websocket = new WebSocket(socket.connectURL)
socket.websocket.onmessage = (e: any) => {
if (receiveMessage) {
receiveMessage(e)
}
}
socket.websocket.onclose = (e: any) => {
socket.socket_open = false
// 需要重新连接
if (socket.is_reonnect) {
socket.reconnect_timer = setTimeout(() => {
// 超过重连次数
if (socket.reconnect_current > socket.reconnect_count) {
clearTimeout(socket.reconnect_timer)
socket.is_reonnect = false
return
}
// 记录重连次数
socket.reconnect_current++
socket.reconnect()
}, socket.reconnect_interval)
}
}
// 连接成功
socket.websocket.onopen = function () {
socket.socket_open = true
socket.is_reonnect = true
// 开启心跳
socket.heartbeat()
}
// 连接发生错误
socket.websocket.onerror = function () { }
},
heartbeat: () => {
socket.hearbeat_timer && clearInterval(socket.hearbeat_timer)
socket.hearbeat_timer = setInterval(() => {
let data = {
token: storage.get('token')
}
socket.send(data)
}, socket.hearbeat_interval)
},
send: (data, callback = null) => {
// 开启状态直接发送
if (socket.websocket.readyState === socket.websocket.OPEN) {
socket.websocket.send(JSON.stringify(data))
callback && callback()
} else {
clearInterval(socket.hearbeat_timer)
message({
type: 'warning',
message: 'socket链接已断开',
duration: 1000,
})
}
},
close: () => {
socket.is_reonnect = false
socket.websocket.close()
},
/**
* 重新连接
*/
reconnect: () => {
if (socket.websocket && !socket.is_reonnect) {
socket.close()
}
socket.init(null)
},
}
export default socket;
// 在组件中使用
import {
ref,
defineComponent,
onBeforeMount,
onUnmounted,
} from 'vue'
import socket from '@/utils/socket'
export default defineComponent({
setup(){
const data = ref('')
const receive = (message: any) => {
console.log('message', message.data)
data.value = message.data
}
onBeforeMount(() => {
socket.init(receive)
})
onUnmounted(() => {
socket.close()
})
return { data }
}
})
浙公网安备 33010602011771号