1/** 2 * å¤é¡µç¾å ±äº« WebSocket è¿æ¥ Worker 3 * ææåæºé¡µç¾è¿æ¥å°åä¸ä¸ª SharedWorkerï¼å ±äº«ä¸ä¸ª WebSocket è¿æ¥ 4 */ 5(function () { 6 'use strict'; 7 8 var ws = null; 9 var currentUrl = null; 10 var heartbeatInterval = 30000; 11 var heartbeatTimer = null; 12 13 /** @type {Set<MessagePort>} */ 14 var ports = new Set(); 15 /** @type {Map<MessagePort, boolean>} */ 16 var portInterests = new Map(); 17 18 // ======================== WebSocket 管ç ======================== 19 20 function connect(url) { 21 if (url === currentUrl && ws && ws.readyState === WebSocket.OPEN) { 22 return; 23 } 24 25 if (ws) { 26 closeWebSocket(); 27 } 28 29 currentUrl = url; 30 31 try { 32 ws = new WebSocket(url); 33 setupEventListeners(); 34 } catch (error) { 35 broadcast({ type: 'error', message: 'WebSocketå建失败: ' + error.message }); 36 } 37 } 38 39 function setupEventListeners() { 40 if (!ws) return; 41 42 ws.onopen = function () { 43 startHeartbeat(); 44 broadcast({ type: 'open' }); 45 }; 46 47 ws.onmessage = function (event) { 48 if (event.data === 'pong') return; 49 50 try { 51 var data = JSON.parse(event.data); 52 broadcast({ type: 'message', data: data }); 53 } catch (_) { 54 broadcast({ type: 'message', data: event.data }); 55 } 56 }; 57 58 ws.onerror = function () { 59 broadcast({ type: 'error', message: 'WebSocketè¿æ¥é误' }); 60 }; 61 62 ws.onclose = function (event) { 63 stopHeartbeat(); 64 65 if (event.code === 3000) { 66 broadcast({ type: 'error', message: 'è¿æ¥è¢«æ°è¿æ¥æ¿æ¢' }); 67 } 68 69 broadcast({ type: 'close', code: event.code, reason: event.reason }); 70 }; 71 } 72 73 function startHeartbeat() { 74 stopHeartbeat(); 75 heartbeatTimer = setInterval(function () { 76 if (ws && ws.readyState === WebSocket.OPEN) { 77 ws.send(JSON.stringify({ type: 'ping' })); 78 } 79 }, heartbeatInterval); 80 } 81 82 function stopHeartbeat() { 83 if (heartbeatTimer) { 84 clearInterval(heartbeatTimer); 85 heartbeatTimer = null; 86 } 87 } 88 89 function closeWebSocket() { 90 stopHeartbeat(); 91 if (ws) { 92 ws.close(); 93 ws = null; 94 } 95 currentUrl = null; 96 } 97 98 function sendData(data) { 99 if (!ws || ws.readyState !== WebSocket.OPEN) { 100 return false; 101 } 102 try { 103 var message = typeof data === 'object' ? JSON.stringify(data) : data; 104 ws.send(message); 105 return true; 106 } catch (error) { 107 broadcast({ type: 'error', message: 'åéæ¶æ¯å¤±è´¥: ' + error.message }); 108 return false; 109 } 110 } 111 112 // ======================== 端å£ç®¡ç ======================== 113 114 function broadcast(message) { 115 ports.forEach(function (port) { 116 try { 117 port.postMessage(message); 118 } catch (_) { 119 ports.delete(port); 120 } 121 }); 122 } 123 124 function shouldClose() { 125 var anyInterested = false; 126 portInterests.forEach(function (interested) { 127 if (interested) anyInterested = true; 128 }); 129 if (!anyInterested) { 130 closeWebSocket(); 131 } 132 } 133 134 // ======================== SharedWorker å ¥å£ ======================== 135 136 self.onconnect = function (event) { 137 var port = event.ports[0]; 138 ports.add(port); 139 portInterests.set(port, true); 140 141 port.addEventListener('message', function (e) { 142 var msg = e.data; 143 144 switch (msg.type) { 145 case 'connect': 146 portInterests.set(port, true); 147 connect(msg.url); 148 // å¦æè¿æ¥å·²å¤äº OPENï¼å URL å¤ç¨ï¼ï¼ç«å³å该 port åç¬åå¤å½åç¶æ 149 // å¦åè°ç¨æ¹ç Promise ä¼å æ¶ä¸å° open äºä»¶èæ°¸ä¹ æèµ· 150 if (ws && ws.readyState === WebSocket.OPEN) { 151 port.postMessage({ type: 'open' }); 152 } 153 break; 154 case 'disconnect': 155 portInterests.set(port, false); 156 shouldClose(); 157 break; 158 case 'send': 159 sendData(msg.data); 160 break; 161 } 162 }); 163 164 port.start(); 165 166 port.addEventListener('close', function () { 167 ports.delete(port); 168 portInterests.delete(port); 169 shouldClose(); 170 }); 171 }; 172})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.