我正在建立一个 ws 连接,但在某些情况下,我需要/想要干净地中止请求,而控制台不会记录这样的错误 -
WebSocket 连接到 'ws://xyz:3001/?失败:WebSocket 已关闭 在建立连接之前。
代码如下:
const ws = new WebSocket(`${url}`);
setTimeout(() => ws.close(), random); // some other event that occur at any given time "random"
一个简单的用例是,当用户打开视图时启动连接,但随后快速关闭视图,这可能/应该中止连接请求。
有没有办法彻底中止连接请求,这样我就不会在浏览器控制台中收到太多类似的日志?
readyState
属性是否有帮助。
您可以在尝试关闭连接之前使用它来检查连接的当前状态。这将允许您避免在连接未处于打开状态时尝试关闭连接,从而防止错误消息出现在控制台中。
WebSocket API 通过
readyState
属性提供不同的状态:
CONNECTING
(0): 连接尚未打开。OPEN
(1):连接已打开并准备好进行通信。CLOSING
(2): 连接正在关闭中。CLOSED
(3): 连接已关闭或无法打开。您可以使用这些状态来决定何时适合关闭 WebSocket:
const ws = new WebSocket(`${url}`);
setTimeout(() => {
// Check if the WebSocket's state is CONNECTING or OPEN before attempting to close it
if (ws.readyState === WebSocket.CONNECTING || ws.readyState === WebSocket.OPEN) {
ws.close();
}
}, random); // some other event that occur at any given time "random"
该代码修改确保仅当 WebSocket 仍在连接或已打开时才调用
ws.close()
。如果 WebSocket 正在关闭或已经关闭,再次调用 close()
可能会导致不必要的错误或日志。
我 99% 确信调用
会在控制台中记录错误,我只想有效地删除本地侦听器并放入 voidws.close() when ws.readyState === WebSocket.CONNECTING
考虑到 WebSocket API 在直接处理此特定用例方面的局限性,您可以考虑使用标志来防止提前关闭的操作。
let proceedWithConnection = true;
const ws = new WebSocket(`${url}`);
// Set up WebSocket event listeners
ws.onopen = () => {
if (!proceedWithConnection) {
ws.close(); // Close immediately if we have decided not to proceed
} else {
// Proceed with setting up the connection
}
};
// Some other event that might occur at any given time
setTimeout(() => {
proceedWithConnection = false;
}, random);
或者您可以延迟实际的连接尝试,直到您更确定需要它。这可能涉及设置初步延迟(如前所述,消除连接尝试的抖动),以确保用户的操作需要 WebSocket 连接:
let shouldConnect = true;
setTimeout(() => {
if (shouldConnect) {
const ws = new WebSocket(`${url}`);
// Set up your WebSocket connection here
}
}, delayBeforeConnecting);
// Some event indicates the connection should not proceed
setTimeout(() => {
shouldConnect = false;
}, random);
whatwg/websockets
第57期相关,其中来自Chromium项目的Adam Rice (ricea
)补充道:
WebSocket
方法已经可以用来执行此操作。如果您不喜欢 Chrome 在发生这种情况时打印控制台消息的行为,您应该在 https://crbug.com/. 提交问题close()
来取消握手。AbortController
我们不太可能将其添加到 WebSocket API 中,因为它可以使用类似的函数轻松模拟
function AbortableWebSocket(url, signal) { signal.throwIfAborted(); const ws = new WebSocket(url); const abortHandler = () => ws.close(); signal.addEventListener('abort', abortHandler); ws.addEventListener('close', () => signal.removeEventListener('abort', abortHandler)); return ws; }
signal.throwIfAborted()
调用将确保,如果在启动 WebSocket 连接之前操作已中止,它将立即抛出异常,从而阻止连接。ws.close()
来终止尝试。连接成功打开后,它将删除中止事件侦听器以清理资源。
您可以向该函数添加所有 WebSocket 事件侦听器的错误处理和清理,以确保没有泄漏:
function AbortableWebSocket(url, signal) {
signal.throwIfAborted();
const ws = new WebSocket(url);
const abortHandler = () => ws.close();
signal.addEventListener('abort', abortHandler);
// Cleanup function to remove all listeners
const cleanup = () => {
signal.removeEventListener('abort', abortHandler);
ws.removeEventListener('open', onOpen);
ws.removeEventListener('error', onError);
ws.removeEventListener('close', onClose);
};
const onOpen = () => cleanup();
const onError = () => cleanup();
const onClose = () => cleanup();
ws.addEventListener('open', onOpen);
ws.addEventListener('error', onError);
ws.addEventListener('close', onClose);
return ws;
}