如何捕捉“WebSocket连接到'ws://xxx:nn'失败:在接收握手响应之前关闭连接”的错误?

80

假设我有一个使用端口号nn启动的节点服务器,并且没有任何WebSocket服务。

问题是我的客户端尝试连接到此服务器的WebSocket服务。

显然,它应该无法连接到服务器。

但是我无法捕获此错误,我的客户端代码如下:

try {
    this.ws = new WebSocket('ws://xxx:nn');
} catch ( e ) {
    fallback();
    console.warn(e);
}

我期望在连接失败时调用fallback方法,但实际上以上的try...catch无法捕获错误。

有谁知道如何在我的用例中捕获错误吗?


6
你最终找到了解决办法吗? - orange
5
可能是Javascript doesn't catch error in WebSocket instantiation的重复问题。 - Eliran Malka
EliranMalka提到,这个错误无法被捕获,因为它是异步发出的,而不是抛出的。 - bFunc
需要一个 Promise 版本的 Websocket,这样错误就可以在 Promise 的 catch 块中异步捕获,而不像现在一样强制输出到控制台。 - Jonathan
4个回答

21

9
不行,我试过了。我的情况是我有一个运行在端口 nn 上的服务器,但它上面没有任何 WebSocket 服务。当客户端通过 WebSocket 尝试连接此服务器时,会抛出错误,无论是 try..catch 还是 onerror 都无法捕获此异常。 - Howard
2
好的@Howard。在我的示例(http://jsfiddle.net/g28yuymv/10/)中,如果请求的端口上没有WS服务运行,我可以获得onError事件。如果您在任何公共云上托管了任何WS服务,请告诉我测试URL。根据我的理解,您正在遇到“500内部服务器错误”的行为。 - shivakumar
谢谢。我可以为这个行为做更多的测试。 - Howard
18
以上是正确的;像上面那样的事件处理程序确实会在连接错误发生时运行。 之所以可能看起来好像错误没有被处理,是因为即使你在这里处理了它,仍然会将醒目的红色错误文本记录到控制台中。据我所知,目前还没有任何方法可以停止这种醒目的红色错误文本的出现。 - JMTyler
1
这是套接字对象上的已触发错误事件,而不是实际抛出的错误对象。在 Chrome 中出现连接错误的情况下,错误事件不包含任何有用信息,例如错误消息,我们只知道 WebSocket 上发生了某些错误。 - Phil
显示剩余4条评论

13

查看HTML5 WebSocket规范,您可以将一个值传递到close()方法中。然后在onclose()事件监听器中,您可以检查该值。这为您提供了设置不同断开连接场景的处理程序的机会,然后将其他所有内容作为通用错误处理。

https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#close()

var _websocket;

function wsConnect() {
  if (_websocket) {
    _websocket.close(3001);
  } else {
    _websocket = new WebSocket("wss://echo.websocket.org1");
    _websocket.onopen = function() {
      console.log('connected');
    };
    _websocket.onmessage = function(msg) {
      console.log(msg);
    };

    _websocket.onclose = function(evt) {
      if (evt.code == 3001) {
        console.log('ws closed');
        _websocket = null;
      } else {
        _websocket = null;
        console.log('ws connection error');
      }
    };

    _websocket.onerror = function(evt) {
      if (_websocket.readyState == 1) {
        console.log('ws normal error: ' + evt.type);
      }
    };
  }
}

wsConnect();

优秀的jsfiddle代码示例:https://jsfiddle.net/lamarant/ry0ty52n/


我想在我的脚本尝试重新连接到WebSocket服务器时捕获ECONREFUSED错误,上面的代码完美地工作了,它避免了我的Node.js脚本在重新连接期间崩溃。 - Jayant

2
上面的答案可能不正确。你想把它看作是一个错误,但这个消息更像是一个警告/信息,当以下情况发生时会显示出来。最初的回答。
WebSocketTransport.prototype.close = function() {
  debug('close');
  var ws = this.ws;
  this._cleanup();
  if (ws) {
    ws.close();
  }
};

正确的应该是:

exampleSocket.onclose = async (event) => {
        console.error(event);    
//do what you want
}

-3

当连接成功时,readyState属性设置为1,因此它可以用于确定连接状态,套接字连接通常需要小于1秒,因此我们可以安全地间隔3秒然后检查连接状态。

以下是代码:

this.ws = new WebSocket('ws://xxx:nn');

setTimeout(() => {
   if (this.ws.readyState !== 1) {
       alert("Problem connection , kindly contact system admin .");
   }
}, 3000);

请在您的答案中添加代码说明。 - rgettman
2
不能假设3秒超时是安全的,因为连接质量差(例如移动电话)或慢速服务器很容易需要超过3秒。在确定问题存在之前,还需要考虑readyState是否正在连接readyState === 0 - thesmart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接