浏览器JS WebSocket仅首次发信成功 按键触发发送异常排查
问题原因
你的代码存在两个核心逻辑错误,直接导致回调不执行、消息发不出去:
- 对
WebSocket.onopen的触发时机理解完全错误:这个事件仅在WebSocket连接从「正在连接」切换到「连接成功」的瞬间触发1次,连接保持打开的整个生命周期里不会重复触发。你初始化WebSocket时第一次绑定的onopen已经在连接建立时触发过、发完"L"了,后续你在按键事件里反复给websocket.onopen赋新的回调函数,根本等不到事件触发——连接早就处于打开状态了,不会再抛open事件,你写的这些回调自然永远不会执行。 - 页面跳转逻辑会直接销毁当前上下文:就算你写的回调能触发,你把
window.location.href = 'xxx'写在websocket.send()前面,浏览器执行到跳转语句时会立刻卸载当前页面,销毁所有JS运行上下文、断开WebSocket连接,后面的send根本没机会执行;就算把send挪到跳转前面,也可能因为页面卸载太快导致消息没发完就断连。
另外你写的按键状态跟踪逻辑也有bug:只在keydown事件里把对应键的状态设为true,没在keyup事件里重置为false,按过一次A/B之后,对应状态永远为真,后续按任意键都会误触发分支。
修正方案
- 不要在按键事件里重绑onopen回调,发送消息前先判断WebSocket连接状态,连接处于打开状态时直接调用
send()即可。 - 调整执行顺序:先发送WebSocket消息,确认消息发出去之后再执行页面跳转,避免页面提前卸载导致消息丢失。
- 补上keyup事件的状态重置逻辑,加个重复触发判断,避免按住按键时重复执行逻辑。
修正后的核心JS代码参考:
// 清空localStorage window.localStorage.clear(); // 初始化WebSocket连接 const url = "ws://192.168.4.1:1337"; const websocket = new WebSocket(url); // 仅在初始化时绑定一次onopen,处理连接初次建立的逻辑 websocket.onopen = function (event) { console.log('websocket is open'); websocket.send("L"); }; // 可选:加连接错误、关闭日志方便排查问题 websocket.onerror = (e) => console.log('ws connection error', e); websocket.onclose = () => console.log('ws connection closed'); // 记录按键按下状态 const isKeyPressed = { 'a': false, 'b': false, }; // 按键抬起时重置状态 document.onkeyup = (keyUpEvent) => { isKeyPressed[keyUpEvent.key] = false; }; document.onkeydown = (keyDownEvent) => { keyDownEvent.preventDefault(); // 按住按键重复触发时直接跳过 if (isKeyPressed[keyDownEvent.key]) return; isKeyPressed[keyDownEvent.key] = true; if (isKeyPressed['a']) { console.log('a has been pressed'); // 先判断连接是否正常打开 if (websocket.readyState === WebSocket.OPEN) { websocket.send("4G"); console.log('send 4G success'); // 消息发完再跳转页面 window.location.href = '1_1.html'; } else { console.log('ws not connected, send failed'); } } if (isKeyPressed['b']) { console.log('b has been pressed'); if (websocket.readyState === WebSocket.OPEN) { websocket.send("4R"); console.log('send 4R success'); window.location.href = '2_1.html'; } else { console.log('ws not connected, send failed'); } } };
内容的提问来源于stack exchange,提问作者Pietro Manzella
相关产品推荐
相关产品推荐

