2015-06-23 9 views
13

Moje gniazdo aktualnie wyrzuca net :: ERR_CONNECTION_REFUSED, ponieważ serwer nie działa, co chcę w tej chwili zrobić.JavaScript nie przechwytuje błędu w instancji WebSocket

Problem polega na tym, że następujący fragment kodu nie przechwytuje błędu. W konsoli widzę wyjątek na linii 2 (z net :: ERR_CONNECTION_REFUSED), co moim zdaniem nie powinno się zdarzyć, ponieważ jest w instrukcji 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 }; 

Moje pytanie brzmi: dlaczego nie zostanie złapany?

Ostatecznie chcę, aby komunikat o błędzie był wyświetlany w innym miejscu, ale nie mogę go złapać, a wiersz 8 wypisuje obiekt "event", który nie wymienia net :: ERR_CONNECTION_REFUSED, więc nie jestem pewien jak uzyskać komunikat o błędzie.

Odpowiedz

34

WebSocket jest błąd połączenia w czasie powoduje wysłanych zdarzenie, a nie rzucony wartość. Jest tak, ponieważ operacje throw muszą być synchroniczne. Aby obsłużyć wszystkie błędy czasu połączenia jako zgłaszane błędy, konstruktor WebSocket musiałby całkowicie zawiesić wykonywanie wszystkich skryptów i interakcję interfejsu użytkownika do czasu zakończenia uzgadniania WebSocket. Zamiast tego proces połączenia działa asynchronicznie, co pozwala wątkowi przeglądarki kontynuować pracę, podczas gdy połączenie WebSocket inicjuje się w tle. Z powodu asynchronicznego charakteru połączenia, WebSocket musi zgłaszać błędy za pośrednictwem zdarzeń error, ponieważ synchroniczna operacja new WebSocket zakończyła się już w momencie, gdy zadanie asynchronicznego połączenia napotka błąd.

Wiadomość, którą widzisz, jest przeznaczona wyłącznie dla deweloperów; w żaden sposób nie jest dostępny dla skryptu. Nie ma żadnej reprezentacji w środowisku JavaScript. Jest to po prostu czerwono-kolorowy komunikat, który pojawia się w konsoli, informując o tym, you, człowieka patrzącego na przeglądarkę, o błędzie.

Zdarzenie obsługi zdarzenia jest poprawnym miejscem do reagowania na awarię, ale brak informacji o błędzie czasu połączenia z odczytem skryptu jest zgodny z projektem. Z WHATWG spec for the WebSocket API:

klienckie nie może przekazać wszelkie informacje awarii do skryptów w sposób, który pozwoliłby skrypt rozróżnić następujące sytuacje:

  • serwera, którego nazwa hosta nie może zostać rozwiązany.
  • Serwer, do którego nie udało się routować pakietów.
  • Serwer, który odmówił połączenia na określonym porcie.
  • Serwer, który nieprawidłowo wykonał uzgadnianie TLS (np. Nie można zweryfikować certyfikatu serwera).
  • Serwer, który nie ukończył uzgadniania otwierającego (np. Ponieważ nie był to serwer WebSocket).
  • Serwer sieci WebSocket, który wysłał poprawny handshake otwarcia, ale określone opcje, które spowodowały, że klient zrzucił połączenie (np. Serwer określił podprocedurę, której klient nie zaoferował).
  • Serwer WebSocket, który niespodziewanie zamknął połączenie po pomyślnym zakończeniu uzgadniania otwierającego.

[...] Umożliwienie skryptowi rozróżnienia tych przypadków pozwoli skryptowi sondować lokalną sieć użytkownika w ramach przygotowań do ataku.

Przeglądarka celowo pomija wszelkie przydatne informacje wymagane przez specyfikację. Autorzy specyfikacji obawiają się, że dostęp do tych informacji może umożliwić złośliwemu serwisowi sieci Web uzyskanie informacji o twojej sieci, więc wymagają, aby przeglądarki raportowały wszystkie błędy czasu połączenia w nieodróżnialny sposób.

+0

To bardzo pomocne informacje, chociaż nie rozumiem, dlaczego wyjątek nie został "złapany". To wydaje się łamać podstawowe ramy tego języka. Zakładam, że sposobem na zrobienie tego, co chcę, jest obsługa onclose i spojrzenie na kod CloseEvent. – andyhasit

+4

@AndyHasIt dodałem akapit otwierający o tym; Mam nadzieję, że jest wystarczająco jasne. Zasadniczo nie możemy "złapać" błędu, ponieważ synchronicznie kończymy blok "try", zanim próba asynchronicznego połączenia napotka błąd. – apsillers

+0

Ma sens, dzięki za pomoc. – andyhasit

0

Próbowałem stworzyć z nim skrzypce i jestem w stanie zobaczyć drukowaną linię.

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/

+1

Jest to spowodowane innym błędem: "Niebezpieczne połączenie WebSocket może nie zostać zainicjowane ze strony załadowanej przez HTTPS." – dfreeman

+0

Rzeczywiście, przykład jsfiddle przyłapuje błąd, ale jeśli otworzysz konsolę i uruchomisz ją, to nie wykryje błędu. Jak wskazuje Dfreeman, są to różne błędy. – andyhasit

Powiązane problemy