WebSocket(Vue3简易版)

简易版的websocket,废话不多说直接上代码!!!

socket.js部分

import { ElMessage } from 'element-plus'

let URL = 'ws://82.157.123.54:9010/ajaxchattest'
let timer = null
let ws = null
let isConnect = false
let checkHeart = 'check-heart'
let count = 0

// 心跳检测
let heart = {
    timer: null,
    timeout: 20000, // 每20s进行一次心跳检测
    start() {
        this.timer = setTimeout(() => {
            if (isConnect) ws.send(JSON.stringify(checkHeart))
        }, this.timeout)
    },
    reset() {
        clearTimeout(this.timer)
        this.start()
    },
    close() {
        clearTimeout(this.timer)
    }
}

// WebSocket连接
const connectWebsocket = () => {
    if (count > 5) {
        connectCount()
        return
    }
    try { // 正在建立连接
        ws = new WebSocket(URL)
        initWebSocket() // 初始化WebSocket连接
    } catch { // 建立连接出错,重新连接
        connect()
    }
}
// 重新连接WebSocket
function connect() {
    if (isConnect) return
    ElMessage.warning('尝试重新连接WebSocket')
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => { // 每次连接 延迟5s
        count++
        connectWebsocket()
    }, 5000)
}
// 初始化WebSocket连接
function initWebSocket() {
    ws.onopen = function () { // WebSocket连接成功
        isConnect = true
        connectStatus(true)
        ElMessage.success('WebSocket连接成功')
    }
    ws.onerror = function () { // WebSocket连接发生错误
        isConnect = false
        connectStatus(false)
        connect()
        heart.start() // 开始心跳检测
        ElMessage.error('WebSocket连接发生错误,正在尝试重新连接')
    }
    ws.onclose = function (e) { // 已关闭WebSocket连接
        isConnect = false
        connectStatus(false)
        heart.close() // 关闭心跳检测
        ElMessage.warning('已关闭WebSocket连接')
    }
    ws.onmessage = function (e) { // 接收到服务端发送的数据
        heart.reset() // 重置心跳检测
        if (e.data === checkHeart) return // 心跳检测
        receive(e.data)
    }
}
function connectCount() {
    ElMessage.error('WebSocket连接失败')
    clearTimeout(timer)
}

// 发送消息
const webSocketSend = (data) => {
    let code = ws?.readyState
    switch (code) {
        case 1:
            sendSock(data)
            break;
        case 2:
            ElMessage.warning('WebSocket连接正在关闭中,请重新连接后再发送消息')
            break;
        default:
            ElMessage.error('请先建立WebSocket连接')
            break;
    }
}
function sendSock(data) {
    ws.send(JSON.stringify(data))
    ElMessage.success('消息发送成功')
}

// 关闭连接
const closeWebSocket = () => {
    if (isConnection()) ws.close()
}
// 是否已连接
function isConnection() {
    return ws?.readyState === 1
}

// 自定义事件
function receive(data) {
    let event = new CustomEvent('receive', { detail: data })
    window.dispatchEvent(event)
}
function connectStatus(status) {
    let event = new CustomEvent('connectStatus', { detail: status })
    window.dispatchEvent(event)
}

export default {
    connectWebsocket,
    closeWebSocket,
    webSocketSend,
    isConnection
}

vue部分 

<template>
  <div>
    <span>WebSocket状态:</span>
    <el-switch :disabled="true" v-model="status" class="ml-2" />
  </div>
  <el-button type="success" @click="connect">连接</el-button>
  <el-button type="danger" @click="closeConnect">断开连接</el-button>
  <el-input class="msg" v-model="content" placeholder="请输入消息" />
  <el-button type="primary" :disabled="!content" @click="send"
    >发送消息</el-button
  >
  <div v-for="(item, index) in list" :key="index">
    <div class="time">{{ item.role }} {{ item.time }}</div>
    <div class="info" v-html="item.con"></div>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, onBeforeUnmount } from "vue";
import dayjs from "dayjs";
import socket from "@/utils/socket.js";

let content = ref("");
let status = ref(false);
let list = reactive([]);

onMounted(() => {
  window.addEventListener("receive", getServerInfo);
  window.addEventListener("connectStatus", getConnectStatus);
});

const connect = () => {
  socket.connectWebsocket();
};
const closeConnect = () => {
  if (socket.isConnection()) socket.closeWebSocket();
};
const send = () => {
  socket.webSocketSend(content.value);
  if (socket.isConnection()) {
    list.push({
      role: "你发送的信息",
      time: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
      con: content.value,
    });
    content.value = "";
  }
};
const getServerInfo = (res) => {
  list.push({
    role: "服务器回应",
    time: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
    con: res.detail,
  });
};
const getConnectStatus = (res) => {
  status.value = res.detail;
};
onBeforeUnmount(() => {
  closeConnect();
  if (socket.isConnection()) {
    window.removeEventListener("receive");
    window.removeEventListener("connectStatus");
  }
});
</script>
<style lang="scss" scoped>
.msg {
  display: block;
  margin: 20px 0;
}
.time {
  font-size: 12px;
  color: var(--el-color-success);
}
.info {
  font-size: 12px;
  color: var(--el-color-primary);
}
</style>

效果图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值