踩坑1:websocket异步执行导致执行多次
目的:
想编写一个websocket自动重连功能
方法:
当连接断开时,利用.onclose
创建定时任务,定时尝试创建websocket连接。
异常现象:
定时任务间隔在2秒以内,当网络通畅后,最后有多个websocket同时建立。
原因:
定时任务创建websocket是异步执行,但没有在任务内判断上一个websocket重连是否已执行结束。
websocket异步导致任务执行后没有立即尝试连接websocket,而是等了2秒多才执行,推迟到了下一个2秒后的定时任务执行周期内,导致最后网络畅通时多个websocket都尝试创建并成功。
解决:
尝试重连的任务内使用options.ws.readyState
判断上次尝试是否结束且失败。
正常代码:文章来源:https://www.toymoban.com/news/detail-412830.html
// 初始化
Usocket.prototype.init = function() {
let options = this.options; // 此方法所属类的属性,当做普通对象变量即可。
if ( 'WebSocket' in window) {
let heartbeat_id = undefined;
let offline_recover_id = undefined;
let create_socket = () => { // 创建websocket连接的匿名函数
console.log("执行create_socket");
options.ws = new WebSocket(options.socket_url);
options.ws.onopen = () => {
console.log("已建立连接");
if (offline_recover_id === undefined) {
console.log("断线重连未开启");
} else {
clearInterval(offline_recover_id);
offline_recover_id = undefined;
}
// 定时心跳
let heartbeat_i = 0;
heartbeat_id = setInterval(function () {
console.log("心跳包发送:" + heartbeat_i++);
options.ws.send("");
}, options.heartbeat_time);
options.onopen();
};
options.ws.onmessage = options.onmessage;
options.ws.onclose = () => {
clearInterval(heartbeat_id);
options.onclose();
if (offline_recover_id === undefined) {
console.log("创建offline_recover_id");
offline_recover_id = setInterval(function () {
console.log("开始执行定时器函数");
if (options.ws.readyState == options.ws.CLOSED) {
create_socket();
} else {
console.log("ws未关闭,本次不执行重连");
}
}, options.offline_recover_time);
}
}
options.ws.onerror = () => {
options.onerror;
}
};
create_socket();
} else {
console.log('您的浏览器不支持WebSocket');
}
};
踩坑2:同一浏览器内,websocket后的alert会阻塞其他页面的js执行
测试了websocket.onmessage接收消息,setInterval任务,估计是阻塞全浏览器js。
测试代码:文章来源地址https://www.toymoban.com/news/detail-412830.html
<html>
<script type="text/javascript">
if ( 'WebSocket' in window) {
var ws = new WebSocket("ws://127.0.0.1:2000");
console.log(".onopen设置前");
ws.onopen = function()
{
// ws.send("js的webscoket数据");
console.log("执行.onopen,scoket开始建立连接...");
};
console.log(".onopen设置后");
ws.onmessage = function (evt)
{
var received_msg = evt.data;
console.log('js接收到:'+received_msg);
alert('js接收到:'+received_msg); // 此行会触发alert阻塞其他页面js,也可用于打开多个此页面时来验证阻塞(此页面A触发时,此页面B被阻塞)
};
ws.onclose = function()
{
alert('close');
console.log("连已关闭...");
};
setInterval(function () {
console.log("心跳包发送");
ws.send("");
}, 5000);
setInterval(function () { // 此行测试阻塞setInterval
let a = 0;
console.log(a++);
})
} else {
alert('您的浏览器不支持WebSocket');
}
function test_webSocket()
{
let user = {
'username' : 'xiaoming',
'key' : 'zdkj-123456',
'action' : 'broadcast',
'data' : {
'msg' : 'js广播测试数据'
}
};
// ws.send("js的webscoket数据");
//console.log(JSON.stringify(user));
ws.send(JSON.stringify(user));
}
</script>
<body>
<div id="">
<a href="javascript:test_webSocket()">发送 WebSocket请求</a>
</div>
</body>
</html>
到了这里,关于JavaScript 踩坑 WebSocket的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!