使用场景: 智能助手实时问答
注意:
- this.$socket 和this.sockets 是有区别的, 监听使用的是this.sockets, 发消息是this.$socket
- 自动连接和自动重连有时会不生效, 需要做重连机制
- 如果项目访问链路比较长, 需要多个nginx转发, 导致websocket返回慢或者断连, 需要在每个转发的服务上加上长连接配置:
location =/域名/接口/ { //例如 /intellitent/aipLlWs/
proxy_pass http://要转发到的服务地址/接口名/; // http://20.20.342:8080/aipLlWs/
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
1. npm i vue-socket.io
2. main.js 文件
import VueSocketIo from 'vue-socket.io'
const IO = new VueSocketIo ({
debug: true,
connection: 'http://****:8080', // 服务器地址
options: {
query: 'ssx', // 参数
path: '/intelligent/aaaaa', // 路径
pingInterval: 2000, // 心跳间隔, 检测连接是否处于活跃状态
tansports: ['websocket'], // 指定通信方式: websocket、polling、flashsocket
// reconnenction: true, // 是否开启重连
// autoConnet: true // 是否自动连接
}
})
Vue.use(IO)
3. 封装socket.vue
<template>
<div>
<!-- <button>发消息</button> -->
</div>
</template>
<script>
export default {
name: 'SocketUtils',
data () {
return {
socket: '',
time: 0,
reconnectTimer: null
}
},
watch: {
// 监听socket的状态
'$socket.io.readyState': {
handler (val) {
// 如果状态返回closed, 调用重连机制
if (val && val == 'closed'){
clearTimeout(this.reconnectTimer)
this.tryReconnect('closed')
}
},
deep: true,
immediate: true
}
},
mounted (){
// 初始化
if (!this.$socket) {
this.$socket.open() // 手动建立连接
}
},
sockets: {
connect () {
console.log('socket 连接成功')
},
reconnect () {
console.log('socket 重连成功')
},
// 监听订阅事件, 和后端约定好
llmSocketEvent (msg) {
console.log('socket 数据')
},
disconnect () {
console.log('socket 断开连接')
clearTimeout(this.reconnectTimer)
this.tryReconnect('disconnect')
}
},
methods: {
// 重连机制
tryReconnect (eventName) {
this.reconnectTimer = setTimeout(() => {
if (this.$socket == null || this.$route.path != '/chat') {
return
}
console.log('socket 开始重连')
if (eventName == 'closed') {
this.$socket.open((err) => {
if (err) {
this.tryReconnect(eventName)
}
})
} else {
this.$socket.connect((err) => {
if (err) {
this.tryReconnect(eventName)
}
})
}
})
}
},
destroyed () {
// 销毁
if (!this.$socket) {
return
}
this.sockets.unsubscribe('llmSocketEvent') // 取消订阅事件
this.$socket.close() // 关闭socket
}
}
</script>
4. 引用组件 (chat/index.vue)
<template>
<div>
、、、、、、、、、
<!-- socket组件 -->
<SocketUtils></SocketUtils>
</div>
</template>
<script>
import SocketUtils from '@/components/Websocket/socket.vue'
export default {
components: { SocketUtils }
}
</script>