长城汽车软件包管理平台
whychdw
2025-05-06 4a867727d81b9513e675ad396903368c6a293dca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// useWebSocket.js
import { ref, onMounted, onUnmounted } from "vue";
import getWsUrl from "@/utils/getWsUrl";
import mitt from "mitt";
 
/**
 *
 * @param url socket的名称
 * @returns {{socket: Ref<UnwrapRef<null>>, isConnected: Ref<UnwrapRef<boolean>>, message: Ref<UnwrapRef<string>>, sendData: sendData, eventBus: Emitter<Record<EventType, unknown>>}}
 */
export default function (url: string) {
  url = getWsUrl(url);
  const socket = ref<WebSocket>();
  const isConnected = ref(false);
  const message = ref("");
 
  const eventBus = mitt();
  let isManualClose = ref(false); // 是否手动关闭
  let reconnectTimer: any; // 重连计时器
  const reconnectInterval = 1000; // 初始重连间隔(ms)
  const maxInterval = 30000; // 最大重连间隔(ms)
  let retryCount = 0; // 重连计数
 
  const connect = () => {
    if (socket.value) {
      socket.value.close();
    }
    socket.value = new WebSocket(url);
    socket.value.onopen = () => {
      isConnected.value = true;
      retryCount = 0;
      console.log("WebSocket Connected, url: ", url);
      eventBus.emit("onopen", true);
    };
 
    socket.value.onmessage = (event) => {
      // 处理接收到的消息
      // console.log("Received:", event.data);
      // 可以在这里通过 emit 发送消息到组件
      message.value = event.data;
      eventBus.emit("message", event.data);
    };
 
    socket.value.onerror = (error) => {
      console.error("WebSocket Error:", error, url);
      eventBus.emit("error", error);
      socket.value?.close();
    };
 
    socket.value.onclose = () => {
      isConnected.value = false;
      // 手动关闭就不需要再重连了
      if (isManualClose.value) return;
      console.log("WebSocket 连接已关闭, url: ", url);
      scheduleReconnect();
    };
  };
 
  // 发送数据
  const sendData = (data: any) => {
    console.log(socket.value?.readyState);
    if (socket.value && socket.value.readyState === socket.value.OPEN) {
      console.log("send", data, "=============");
      socket.value.send(data);
    }
  };
 
  // 定时重连(指数退避)
  const scheduleReconnect = () => {
    const delay = Math.min(reconnectInterval * 2 ** retryCount, maxInterval);
    console.log(`第${retryCount + 1}次重试,${delay}ms后重连${url}`);
    reconnectTimer = setTimeout(() => {
      retryCount++;
      connect();
    }, delay);
  };
 
  const close = () => {
    isManualClose.value = true; // 手动关闭
    if (socket.value) {
      socket.value.close();
    }
    clearTimeout(reconnectTimer);
  };
 
  onMounted(() => {
    connect();
  });
 
  onUnmounted(() => {
    close();
  });
 
  // 返回 socket 对象和状态
  return { socket, isConnected, message, sendData, eventBus };
}