Javascript 不会在 WebSocket 实例化中捕获错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31002592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 13:06:31  来源:igfitidea点击:

Javascript doesn't catch error in WebSocket instantiation

javascript

提问by andyhasit

My socket currently throws net::ERR_CONNECTION_REFUSED because the server isn't running, which I want it to do at the moment.

我的套接字当前抛出 net::ERR_CONNECTION_REFUSED 因为服务器没有运行,我现在希望它这样做。

The problem is that the following piece of code doesn't catch the error. In the console I see an exception on line 2 (with net::ERR_CONNECTION_REFUSED) which I believe shouldn't happen as it's within a try statement.

问题是以下代码没有捕获错误。在控制台中,我在第 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  };

So my question is why is it not being caught?

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

What I ultimately want is the error message to be displayed elsewhere, but I can't catch it, and line 8 prints an "event" object which doesn't mention net::ERR_CONNECTION_REFUSED, so I'm not sure how to get the error message out.

我最终想要的是在别处显示的错误消息,但我无法捕捉到它,第 8 行打印了一个没有提及 net::ERR_CONNECTION_REFUSED 的“事件”对象,所以我不知道如何获得错误信息出来。

回答by apsillers

The WebSocket's connection-time error causes a dispatched event, not a thrown value. This is because throwoperations must be synchronous. In order to handle all connection-time errors as thrown errors, the WebSocketconstructor would need to completely suspend all script execution and UI interaction until the entire WebSocket handshake had completed. Instead, the connection process runs asynchronously, thereby allowing the browser thread to continue working while the WebSocket connection initializes in the background. Because of the connection's asynchronous nature, the WebSocketmust report errors via errorevents, since the synchronous new WebSocketoperation has already finished by the time the asynchronous connection task encounters an error.

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

The ERR_CONNECTION_REFUSEDmessage you see is purely for the benefit of developers; it is not accessible to the script in any way. It does not have any representation within the JavaScript environment. It's just a red-colored message that appears in your console to inform you, the human looking at the browser, about an error.

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

The errorhandler event is the correct place to respond to failure, but the lack of script-readable connection-time error information is by design. From the WHATWG spec for the WebSocket API:

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

User agents must not convey any failure information to scripts in a way that would allow a script to distinguish the following situations:

  • A server whose host name could not be resolved.
  • A server to which packets could not successfully be routed.
  • A server that refused the connection on the specified port.
  • A server that failed to correctly perform a TLS handshake (e.g., the server certificate can't be verified).
  • A server that did not complete the opening handshake (e.g. because it was not a WebSocket server).
  • A WebSocket server that sent a correct opening handshake, but that specified options that caused the client to drop the connection (e.g. the server specified a subprotocol that the client did not offer).
  • A WebSocket server that abruptly closed the connection after successfully completing the opening handshake.

[...] Allowing a script to distinguish these cases would allow a script to probe the user's local network in preparation for an attack.

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

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

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

The browser is deliberately omitting any useful information as required by the spec. The spec authors are concerned that access to this information could allow a malicious Web page to gain information about your network, so they require browsers report all connection-time errors in an indistinguishable way.

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

回答by Kunal Pradhan

I tried creating fiddle with it and I am able to see line printed.

我试着用它来创造小提琴,我能够看到打印的线条。

host='localhost';
port=100;
try {

    ws = new WebSocket('ws://'+ host + ':' + port + '/');
  }
  catch (err) {
    console.log('This never prints');
  }
  ws.onerror = function (error) {
    console.log(error);
  };

https://jsfiddle.net/xzumgag0/

https://jsfiddle.net/xzumgag0/