RTU/test/web_root/js/ws-client.js

157 lines
3.8 KiB
JavaScript

/**
* ws-client.js — WebSocket 客户端单例
* 全站共享一个 WS 连接,提供自动重连、消息分发、状态通知
*/
var WsClient = (function() {
var ws = null;
var url = '';
var msgCallbacks = [];
var statusCallbacks = [];
var reconnectTimer = null;
var reconnectDelay = 3000;
var status = 'disconnected'; // 'connected' | 'disconnected' | 'connecting'
function setStatus(s) {
if (status !== s) {
status = s;
for (var i = 0; i < statusCallbacks.length; i++) {
statusCallbacks[i](s);
}
}
}
function connect(wsUrl) {
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
return;
}
url = wsUrl;
setStatus('connecting');
try {
ws = new WebSocket(url);
} catch (e) {
setStatus('disconnected');
scheduleReconnect();
return;
}
ws.onopen = function() {
setStatus('connected');
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
};
ws.onclose = function() {
setStatus('disconnected');
ws = null;
scheduleReconnect();
};
ws.onerror = function() {
// onclose will fire after onerror
};
ws.onmessage = function(e) {
var raw = e.data;
// 写入监控日志
if (typeof MonitorRing !== 'undefined') {
MonitorRing.push('↓', raw);
}
// 尝试解析 JSON
var data = null;
try {
data = JSON.parse(raw);
} catch (ex) {
// 非 JSON 消息也分发原始数据
}
// 分发给所有注册的回调
for (var i = 0; i < msgCallbacks.length; i++) {
try {
msgCallbacks[i](data || raw, raw);
} catch (ex) {
console.error('WsClient msg callback error:', ex);
}
}
};
}
function scheduleReconnect() {
if (reconnectTimer) return;
reconnectTimer = setTimeout(function() {
reconnectTimer = null;
if (status === 'disconnected') {
connect(url);
}
}, reconnectDelay);
}
function send(data) {
var raw = '';
if (typeof data === 'object') {
raw = JSON.stringify(data);
} else {
raw = String(data);
}
// 写入监控日志
if (typeof MonitorRing !== 'undefined') {
MonitorRing.push('↑', raw);
}
if (!ws || ws.readyState !== WebSocket.OPEN) {
console.error('WsClient: not connected, cannot send');
return false;
}
try {
ws.send(raw);
return true;
} catch (e) {
console.error('WsClient: send failed', e);
return false;
}
}
function onMessage(cb) {
msgCallbacks.push(cb);
}
function onStatusChange(cb) {
statusCallbacks.push(cb);
// 立即通知当前状态
cb(status);
}
function getStatus() {
return status;
}
function disconnect() {
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
if (ws) {
ws.onclose = null; // 阻止自动重连
ws.close();
ws = null;
}
setStatus('disconnected');
}
return {
connect: connect,
send: send,
onMessage: onMessage,
onStatusChange: onStatusChange,
getStatus: getStatus,
disconnect: disconnect
};
})();