前端WebSocket实战:别再只会用HTTP了

前端WebSocket实战:别再只会用HTTP了

前端WebSocket实战:别再只会用HTTP了

毒舌时刻

这代码写得跟网红滤镜似的——仅供参考。

各位前端同行,咱们今天聊聊前端WebSocket。别告诉我你还在用轮询获取实时数据,那感觉就像每隔一分钟就去敲门问"好了没"——烦人又低效。

为什么你需要WebSocket

最近看到一个项目,实时聊天功能用轮询实现,每秒请求一次服务器,我差点当场去世。我就想问:你是在做实时通信还是在做DDoS攻击?

反面教材

// 反面教材:轮询获取数据 function startPolling() { setInterval(async () => { const response = await fetch('/api/messages'); const messages = await response.json(); updateMessages(messages); }, 1000); // 每秒请求一次 } // 服务器:求放过 // 带宽:我扛不住了 

毒舌点评:这代码,我看了都替你的服务器着急。每秒轮询一次,你是想让服务器变成蜜蜂吗?

前端WebSocket的正确姿势

1. 基础WebSocket使用

// 正确姿势:基础WebSocket class WebSocketClient { constructor(url) { this.url = url; this.ws = null; this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; this.listeners = new Map(); } connect() { this.ws = new WebSocket(this.url); this.ws.onopen = () => { console.log('WebSocket连接成功'); this.reconnectAttempts = 0; this.emit('open'); }; this.ws.onmessage = (event) => { const data = JSON.parse(event.data); this.emit(data.type, data.payload); }; this.ws.onclose = () => { console.log('WebSocket连接关闭'); this.emit('close'); this.reconnect(); }; this.ws.onerror = (error) => { console.error('WebSocket错误:', error); this.emit('error', error); }; } send(type, payload) { if (this.ws && this.ws.readyState === WebSocket.OPEN) { this.ws.send(JSON.stringify({ type, payload })); } } on(event, callback) { if (!this.listeners.has(event)) { this.listeners.set(event, []); } this.listeners.get(event).push(callback); } emit(event, data) { if (this.listeners.has(event)) { this.listeners.get(event).forEach(callback => callback(data)); } } reconnect() { if (this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnectAttempts++; console.log(`尝试重连... (${this.reconnectAttempts}/${this.maxReconnectAttempts})`); setTimeout(() => this.connect(), 3000); } } disconnect() { if (this.ws) { this.ws.close(); } } } // 使用 const ws = new WebSocketClient('wss://api.example.com/ws'); ws.on('open', () => { console.log('连接成功'); }); ws.on('message', (data) => { console.log('收到消息:', data); }); ws.connect(); 

2. React中使用WebSocket

// 正确姿势:React中使用WebSocket import { useEffect, useRef, useState, useCallback } from 'react'; function useWebSocket(url) { const [isConnected, setIsConnected] = useState(false); const [messages, setMessages] = useState([]); const ws = useRef(null); useEffect(() => { ws.current = new WebSocket(url); ws.current.onopen = () => setIsConnected(true); ws.current.onclose = () => setIsConnected(false); ws.current.onmessage = (event) => { const data = JSON.parse(event.data); setMessages(prev => [...prev, data]); }; return () => { ws.current.close(); }; }, [url]); const sendMessage = useCallback((message) => { if (ws.current && ws.current.readyState === WebSocket.OPEN) { ws.current.send(JSON.stringify(message)); } }, []); return { isConnected, messages, sendMessage }; } // 使用 function ChatRoom() { const { isConnected, messages, sendMessage } = useWebSocket('wss://chat.example.com'); const [input, setInput] = useState(''); const handleSend = () => { sendMessage({ type: 'chat', content: input }); setInput(''); }; return ( <div> <div>状态: {isConnected ? '已连接' : '未连接'}</div> <div className="messages"> {messages.map((msg, i) => ( <div key={i}>{msg.content}</div> ))} </div> <input value={input} onChange={e => setInput(e.target.value)} /> <button onClick={handleSend}>发送</button> </div> ); } 

3. 使用Socket.io

// 正确姿势:使用Socket.io import { io } from 'socket.io-client'; const socket = io('https://api.example.com', { transports: ['websocket'], autoConnect: true, reconnection: true, reconnectionAttempts: 5, reconnectionDelay: 3000 }); // 连接事件 socket.on('connect', () => { console.log('连接成功, ID:', socket.id); }); // 断开连接 socket.on('disconnect', () => { console.log('连接断开'); }); // 监听消息 socket.on('message', (data) => { console.log('收到消息:', data); }); // 发送消息 socket.emit('chat message', { text: 'Hello' }); // 加入房间 socket.emit('join room', 'room-1'); // 离开房间 socket.emit('leave room', 'room-1'); 

毒舌点评:早这么写,你的实时通信早做好了。别告诉我你还在用轮询,那你还是趁早去用短信吧。

实战技巧:WebSocket指南

1. WebSocket使用场景

  • 实时聊天:即时通讯
  • 实时数据:股票、比分
  • 协同编辑:多人协作
  • 在线游戏:实时对战

2. 最佳实践

  1. 重连机制:断线自动重连
  2. 心跳检测:保持连接活跃
  3. 消息确认:确保消息送达
  4. 错误处理:优雅处理异常

最后想说的

WebSocket不是新技术,是实时通信的标准。别再只会用HTTP了——WebSocket一下,你的应用会实时起来。

WebSocket就像电话,HTTP就像写信。紧急的事打电话,不急的事写信。别什么事都写信,学会打电话。

Read more

Qt与Web混合编程:CEF与QCefView深度解析

Qt与Web混合编程:CEF与QCefView深度解析

Qt与Web混合编程:CEF与QCefView深度解析 * 1. 引言:现代GUI开发的融合趋势 * 2. Qt与Web集成方案对比 * 3. CEF核心架构解析 * 4. QCefView:Qt与CEF的桥梁 * 5. 实战案例:智能家居控制面板 * 6. 性能优化策略 * 7. 调试技巧大全 * 8. 安全加固方案 * 9. 未来展望:WebComponent集成 * 10. 结语 1. 引言:现代GUI开发的融合趋势 在当今的桌面应用开发领域,本地GUI框架与Web技术的融合已成为不可逆转的趋势。Qt作为成熟的跨平台C++框架,与Web技术的结合为开发者提供了前所未有的灵活性: * 本地性能 + Web动态性 = 最佳用户体验 * 快速迭代的Web前端 + 稳定可靠的本地后端 * 跨平台一致性 + 现代UI效果 35%25%20%20%混合应用优势分布开发效率UI表现力跨平台性性能平衡 2. Qt与Web集成方案对比 方案优点缺点适用场景Qt WebEngine官方支持,

使用 QWebChannel 实现 JS 与 C++ 双向通信(超详细 + 踩坑总结 + Demo)

使用 QWebChannel 实现 JS 与 C++ 双向通信(超详细 + 踩坑总结 + Demo)

使用 QWebChannel 实现 JS 与 C++ 双向通信(超详细 + 踩坑总结 + Demo) 在基于 QWebEngine 的项目中,要让 前端 JavaScript 与 后端 C++ 互相通信,是非常关键的能力。 Qt 官方提供的方案就是 QWebChannel,它能让你像调用本地对象一样从 JS 访问 C++,并且支持信号/槽、异步回调等。 但实际项目中常见各种问题: * JS 侧无法拿到对象? * 信号不触发? * 跨线程导致闪退? * 对象销毁后 JS 仍然在调用? * Page/Page再创建导致 channel 失效? 本文将带你彻底搞懂 QWebChannel 的机制,避坑,并给出可运行的 Demo。 一、

前端PWA:让你的网站变成App

前端PWA:让你的网站变成App 毒舌时刻 前端PWA?这不是噱头吗? "PWA有什么用,用户直接用浏览器不就好了"——结果用户体验差,无法离线访问, "我有原生App,不需要PWA"——结果开发成本高,维护困难, "PWA就是加个manifest和service worker,多简单"——结果功能不完整,用户体验差。 醒醒吧,PWA不是简单的技术组合,而是一种现代化的Web应用模式! 为什么你需要这个? * 离线访问:即使没有网络也能访问应用 * 安装到主屏幕:像原生App一样方便使用 * 推送通知:及时向用户发送重要信息 * 性能提升:缓存静态资源,加快加载速度 * 跨平台:一次开发,多平台运行 反面教材 <!-- 反面教材:不完整的PWA配置 --> <!DOCTYPE html&

openclaw web UI 无法访问 not found

## 问题解决总结 根本原因 :Gateway 的 resolveControlUiRootSync 函数在自动查找控制 UI 目录时,没有包含 node_modules/openclaw/dist/control-ui 作为候选路径。手动指定相对路径时,可能因为工作目录解析问题无法正确找到目录。 最终解决方案 : 1. 将控制 UI 文件从 node_modules/openclaw/dist/control-ui 复制到项目根目录       E:\你实际的目录\control-ui       (建立一个英文,且没有符号的目录,“-”和“_",会引起混淆) 2. 在配置文件中使用绝对路径指定 controlUi.root: "E:\\你实际的目录\\control-ui" 编辑 openclaw.json "