由于您正在使用 Web 套接字,因此最好使用SharedWorker https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker为您的 Web Sockets 创建一个新线程。和正常人的区别WebWorker
and a SharedWorker
加载页面时,Web Worker 将在每个选项卡或浏览器中创建一个新会话,而共享 Worker 将在每个选项卡中使用相同的会话。因此,您的所有选项卡或窗口都将具有相同的工作线程和相同的 Web Socket 连接来使用。
如果数据更新非常频繁(每秒超过 60 次)并且每次都需要更新 DOM,那么使用requestAnimationFrame https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame方法来限制 DOM 的更新量。它将等待下一个重绘周期,然后再用新内容更新 DOM,大约每秒 60 次,即 60FPS。
其实现如下例所示:
主线程。
// Create shared worker.
const webSocketWorker = new SharedWorker('web-sockets-worker.js');
/**
* Sends a message to the worker and passes that to the Web Socket.
* @param {any} message
*/
const sendMessageToSocket = message => {
webSocketWorker.port.postMessage({
action: 'send',
value: message,
});
};
// Event to listen for incoming data from the worker and update the DOM.
webSocketWorker.port.addEventListener('message', ({ data }) => {
requestAnimationFrame(() => {
appendGatePublicTickersData(data);
});
});
// Initialize the port connection.
webSocketWorker.port.start();
// Remove the current worker port from the connected ports list.
// This way your connectedPorts list stays true to the actual connected ports,
// as they array won't get automatically updated when a port is disconnected.
window.addEventListener('beforeunload', () => {
webSocketWorker.port.postMessage({
action: 'unload',
value: null,
});
webSocketWorker.port.close();
});
共享工作者。
/**
* Array to store all the connected ports in.
*/
const connectedPorts = [];
// Create socket instance.
const socket = new WebSocket("wss://fx-ws.gateio.ws/v4/ws/btc");
// Send initial package on open.
socket.addEventListener('open', () => {
const data = JSON.stringify({
"time": 123456,
"channel": "futures.tickers",
"event": "subscribe",
"payload": ["BTC_USD", "ETH_USD"]
});
socket.send(data);
});
// Send data from socket to all open tabs.
socket.addEventListener('message', ({ data }) => {
const payload = JSON.parse(data);
connectedPorts.forEach(port => port.postMessage(payload));
});
/**
* When a new thread is connected to the shared worker,
* start listening for messages from the new thread.
*/
self.addEventListener('connect', ({ ports }) => {
const port = ports[0];
// Add this new port to the list of connected ports.
connectedPorts.push(port);
/**
* Receive data from main thread and determine which
* actions it should take based on the received data.
*/
port.addEventListener('message', ({ data }) => {
const { action, value } = data;
// Send message to socket.
if (action === 'send') {
socket.send(JSON.stringify(value));
// Remove port from connected ports list.
} else if (action === 'unload') {
const index = connectedPorts.indexOf(port);
connectedPorts.splice(index, 1);
}
});
// Start the port broadcasting.
port.start();
});
旁注:你的appendGatePublicTickersData
不使用await
关键字,因此它不必是async
功能。
从 Safari 16 开始支持。
浏览器对共享 Web Worker 的支持 https://caniuse.com/sharedworkers