问题描述
websocket连接失败后多久会触发error事件?这个时间有没有方法可以设置
问题出现的环境背景
最近项目中用到了websocket,但是连接地址的端口不确定,因此前端需要从某个端口(例如ws://127.0.0.1:9000)开始累加去建立连接,然后通过onerror事件判断连接是否成功,但运行时发现从尝试连接到连接失败触发error事件的时间比较久,大概需要1s。这样如果枚举100次才连接成功,就需要占用100s的时间,效率太慢不可行。
function connectWebSocket(port = 9900) {
return new Promise((resolve, reject) => {
if (ws && ws.readyState === WebSocket.OPEN) {
resolve(ws)
} else {
// 尝试建立连接
console.log('connect', '-------', Date.now())
ws = new WS(`ws://127.0.0.1:${port.toString()}`)
ws.onopen = () => {
// 连接成功
console.log('open', '-------', Date.now())
resolve(ws)
}
// 连接失败触发回调
ws.onerror = () => {
console.log('error', '-------', Date.now())
reject()
}
}
}).catch(() => {
// 累加端口重建websocket
if (port < 65534) {
const newPort = port + 1
return connectWebSocket(newPort)
} else {
ws.close()
ws = null
throw new Error('无法连接服务器')
}
})
}
尝试方法
运行发现open事件大概在建立连接20ms后触发,所以我试图通过setTimeout的方式来代替error事件,代码如下:
function connectWebSocket(port = 9900) {
return new Promise((resolve, reject) => {
// 加入isOpen变量来websocket是否握手成功
let isOpen = false
if (ws && ws.readyState === WebSocket.OPEN) {
resolve(ws)
} else {
console.log('connect', '-------', Date.now())
ws = new WS(`ws://127.0.0.1:${port.toString()}`)
ws.onopen = () => {
// 握手成功设置标识为true
isOpen = true
console.log('open', '-------', Date.now())
resolve(ws)
}
// 需要确保定时器的回调在open事件之后执行
setTimeout(() => {
console.log(5, '-------', Date.now(), isOpen)
if (!isOpen) {
// 如果isOpen为false,说明没有握手成功,接着递归建立连接
ws.close()
reject()
}
}, 20)
// ws.onerror = () => {
// console.log('error', '-------', Date.now())
// reject()
// }
}
}).catch(() => {
if (port < 65534) {
const newPort = port + 1
return connectWebSocket(newPort)
} else {
ws.close()
ws = null
throw new Error('无法连接服务器')
}
})
}
通过以上代码可以把判断是否需要重连的时间压缩到20ms左右,但问题在于我不确定open的触发时机能不能保证在20ms内(可能与电脑性能有关?)。
这种方式是否可行呢,或者定时器的时间设置为多少比较合适。
前端一个个端口扫描?天哪,我听到了网卡在哭泣。
前端不知道地址可以发一个请求先去问一下后端啊,后端自己起的 websocket 服务总归会知道自己用的是什么端口吧。为什么前端要闭着眼睛一个个试呢?