Javascript не улавливает ошибку в создании экземпляра WebSocket

Мой сокет в настоящее время выбрасывает 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  };

Итак, мой вопрос: почему его не поймали?

В конечном итоге я хочу, чтобы сообщение об ошибке отображалось в другом месте, но я не могу его перехватить, и в строке 8 выводится объект "событие", в котором нет упоминания net::ERR_CONNECTION_REFUSED, поэтому я не уверен, как получить сообщение об ошибке.

4 ответа

Решение

WebSocketОшибка времени соединения вызывает отправленное событие, а не выброшенное значение. Это потому что throw операции должны быть синхронными. Чтобы обработать все ошибки времени соединения как выданные ошибки, WebSocket Конструктор должен будет полностью приостановить выполнение всех сценариев и взаимодействие с пользовательским интерфейсом, пока не будет завершено полное рукопожатие WebSocket. Вместо этого процесс подключения выполняется асинхронно, что позволяет потоку браузера продолжать работать, пока подключение WebSocket инициализируется в фоновом режиме. Из-за асинхронного характера соединения WebSocket должен сообщать об ошибках через error события, так как синхронные new WebSocket операция уже завершена к тому времени, когда в задаче асинхронного соединения обнаружена ошибка.

ERR_CONNECTION_REFUSED сообщение, которое вы видите, чисто для блага разработчиков; это не доступно для сценария в любом случае. Он не имеет представления в среде JavaScript. Это просто сообщение красного цвета, которое появляется в вашей консоли, чтобы сообщить вам, человеку, смотрящему в браузер, об ошибке.

error Событие-обработчик - правильное место для ответа на сбой, но отсутствие читаемой сценарием информации об ошибке времени соединения является преднамеренным. Из спецификации WHATWG для API WebSocket:

Пользовательские агенты не должны передавать какую-либо информацию об ошибках в сценарии таким образом, чтобы сценарий мог различать следующие ситуации:

  • Сервер, имя хоста которого не может быть разрешено.
  • Сервер, на который невозможно успешно перенаправить пакеты.
  • Сервер, который отклонил соединение на указанном порту.
  • Сервер, который не смог правильно выполнить квитирование TLS (например, сертификат сервера не может быть проверен).
  • Сервер, который не завершил открывающее рукопожатие (например, потому что это не был сервер WebSocket).
  • Сервер WebSocket, который отправил правильное открывающее рукопожатие, но в котором указаны параметры, которые заставили клиента разорвать соединение (например, сервер указал подпротокол, который клиент не предлагал).
  • Сервер WebSocket, который внезапно закрыл соединение после успешного завершения рукопожатия при открытии.

[...] Разрешение сценарию различать эти случаи позволило бы сценарию проверять локальную сеть пользователя при подготовке к атаке.

Браузер намеренно пропускает любую полезную информацию, как того требует спецификация. Авторы спецификаций обеспокоены тем, что доступ к этой информации может позволить вредоносной веб-странице получить информацию о вашей сети, поэтому они требуют, чтобы браузеры сообщали обо всех ошибках во время соединения неразличимым образом.

Браузеры на базе Chrome: в моем случае я просто хотел избавиться от сообщения об ошибке из консоли. В этом случае вы можете ввести это регулярное выражение в фильтр консоли:

-/Websocket\sconnection.*failed/

const socket = new WebSocket('ws://HOST:PORT'); // create websocket instance

socket.addEventListener('error', (event) => { /* do something */ });
// or the same
socket.onerror = (event) => { /* do something */ };

Я попытался создать скрипку с этим, и я могу видеть напечатанную линию.

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/

Другие вопросы по тегам