Javascript在WebSocket实例化中没有捕获错误

and*_*sit 32 javascript

我的套接字当前抛出net :: ERR_CONNECTION_REFUSED,因为服务器没有运行,我希望它现在可以运行.

问题是以下代码不能捕获错误.在控制台中,我在第2行看到了一个异常(使用net :: ERR_CONNECTION_REFUSED),我认为这不应该发生,因为它在try语句中.

1  try {
2    ws = new WebSocket('ws://'+ host + ':' + port + '/');
3  }
4  catch (err) {
5    console.log('This never prints');
6  }
7  ws.onerror = function (error) {
8    console.log(error);
9  };
Run Code Online (Sandbox Code Playgroud)

所以我的问题是为什么它没被抓住?

我最终想要的是在其他地方显示的错误消息,但是我无法捕捉它,第8行打印出一个"事件"对象,它没有提到net :: ERR_CONNECTION_REFUSED,所以我不知道如何获取错误消息.

aps*_*ers 64

WebSocket记者连线时发生错误导致调度的事件,而不是抛出值.这是因为throw操作必须是同步的.为了将所有连接时错误作为抛出错误处理,WebSocket构造函数需要完全挂起所有脚本执行和UI交互,直到完成整个WebSocket握手.相反,连接进程以异步方式运行,从而允许浏览器线程在WebSocket连接在后台初始化时继续工作.由于连接的异步性质,WebSocket必须通过error事件报告错误,因为new WebSocket异步连接任务遇到错误时同步操作已经完成.

ERR_CONNECTION_REFUSED您看到的信息纯粹是为了开发人员的利益; 脚本无法以任何方式访问它.它在JavaScript环境中没有任何表示.它只是一个红色的消息,出现在你的控制台中,通知,看着浏览器的人,一个错误.

error处理事件是对失败的正确位置,但缺乏剧本可读连接时错误信息是由设计.从WebSocket APIWHATWG规范:

用户代理不得以允许脚本区分以下情况的方式向脚本传达任何故障信息:

  • 无法解析主机名的服务器.
  • 无法成功路由数据包的服务器.
  • 拒绝指定端口上的连接的服务器.
  • 无法正确执行TLS握手的服务器(例如,无法验证服务器证书).
  • 未完成打开握手的服务器(例如,因为它不是WebSocket服务器).
  • WebSocket服务器发送了正确的打开握手,但指定了导致客户端断开连接的选项(例如,服务器指定了客户端未提供的子协议).
  • 成功完成打开握手后突然关闭连接的WebSocket服务器.

[...]允许脚本区分这些情况将允许脚本探测用户的本地网络以准备攻击.

浏览器故意省略规范要求的任何有用信息.规范作者担心访问此信息可能允许恶意网页获取有关您网络的信息,因此他们要求浏览器以难以区分的方式报告所有连接时错误.

  • 但是,如何防止错误显示在控制台中?`ws.onerror = ev => { ev.stopImmediatePropagation() ev.stopPropagation() ev.preventDefault() return false }` 根本没有帮助。 (5认同)
  • @AndyHasIt我添加了一个关于那个的开头段落; 我希望它足够清楚.基本上,我们不能"捕获"错误,因为我们在异步连接尝试遇到错误之前同步退出`try`块. (4认同)
  • @OuuGiii 您*可以*使用 Promise `catch` 方法,但是 `WebSocket` API 不支持 Promise,因此您需要创建自己的 Promise 对象。参见 [我刚刚制作的这个小提琴](http://jsfiddle.net/gyxjq0ma/)。您仍然需要监听错误事件并调用 `reject` 来触发任何 `catch` 机制。你甚至不能`throw`,因为`onerror` 解析是在`new Promise` 函数之外按时间顺序发生的。同样,WebSocket 构造函数在连接失败时所做的只是调度一个恰好名为“error”的事件;它不会引发异常。 (3认同)
  • 这是非常有用的信息,尽管我不明白为什么未“捕获”异常。这似乎破坏了语言的基本框架。我想做我想做的方法是处理onclose并查看CloseEvent的代码。 (2认同)
  • 非常感谢。现在我知道这个错误来自哪里。但是,如果我创建了一个 onerror 处理程序,现在只想删除控制台中调度的事件错误,因为我想为最终用户保持控制台干净,该怎么办? (2认同)
  • 这是不好的。我的 Web 客户端每 1 秒轮询一次未运行的服务器,并每次写入控制台记录此错误。 (2认同)