2015-06-23 40 views
13

Ổ cắm của tôi hiện đang phát ròng :: ERR_CONNECTION_REFUSED vì máy chủ không chạy, mà tôi muốn nó hoạt động tại thời điểm này.Javascript không gặp lỗi trong quá trình khởi tạo WebSocket

Sự cố là đoạn mã sau đây không phát hiện lỗi. Trong giao diện điều khiển, tôi thấy một ngoại lệ trên dòng 2 (với net :: ERR_CONNECTION_REFUSED) mà tôi tin rằng không nên xảy ra vì nó nằm trong một câu lệnh thử.

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 }; 

Vì vậy, câu hỏi của tôi là tại sao nó không bị bắt?

Những gì tôi rốt cuộc muốn là thông báo lỗi sẽ được hiển thị ở những nơi khác, nhưng tôi không thể bắt nó, và dòng 8 in một "sự kiện" đối tượng mà không đề cập net :: ERR_CONNECTION_REFUSED, vì vậy tôi không chắc chắn làm thế nào để có được thông báo lỗi.

Trả lời

34

Các WebSocket 's kết nối thời gian lỗi gây ra một cử sự kiện, không phải là một giá trị ném. Điều này là do các hoạt động throw phải đồng bộ. Để xử lý tất cả các lỗi thời gian kết nối dưới dạng lỗi được ném, hàm tạo WebSocket sẽ cần phải tạm ngưng hoàn toàn tất cả việc thực thi tập lệnh và tương tác giao diện người dùng cho đến khi toàn bộ quá trình bắt tay WebSocket đã hoàn thành. Thay vào đó, quá trình kết nối chạy không đồng bộ, do đó cho phép chuỗi trình duyệt tiếp tục hoạt động trong khi kết nối WebSocket khởi chạy trong nền. Do tính chất không đồng bộ của kết nối, WebSocket phải báo cáo lỗi qua error sự kiện, vì thao tác new WebSocket đồng bộ đã kết thúc khi tác vụ kết nối không đồng bộ gặp lỗi.

Thông báo ERR_CONNECTION_REFUSED bạn thấy hoàn toàn vì lợi ích của nhà phát triển; không thể truy cập vào tập lệnh bằng bất kỳ cách nào. Nó không có bất kỳ biểu diễn nào trong môi trường JavaScript. Nó chỉ là một thông báo màu đỏ xuất hiện trong bảng điều khiển của bạn để thông báo cho bạn, con người đang xem trình duyệt, về một lỗi.

Sự kiện xử lý error là địa điểm chính xác để trả lời lỗi, nhưng thiếu thông tin lỗi thời gian kết nối có thể đọc được theo kịch bản được thiết kế. Từ WHATWG spec for the WebSocket API:

đại lý Người dùng không phải chuyển tải bất kỳ thông tin thất bại trong việc kịch bản trong một cách mà sẽ cho phép một kịch bản để phân biệt các trường hợp sau đây:

  • Một máy chủ có tên máy chủ không thể được giải quyết.
  • Máy chủ mà các gói không thể định tuyến thành công.
  • Máy chủ từ chối kết nối trên cổng được chỉ định.
  • Máy chủ không thực hiện được việc bắt tay TLS đúng cách (ví dụ: không thể xác minh chứng chỉ máy chủ).
  • Máy chủ không hoàn tất việc bắt tay mở (ví dụ: vì nó không phải là máy chủ WebSocket).
  • Máy chủ WebSocket đã gửi bắt tay mở chính xác nhưng các tùy chọn được chỉ định đã khiến khách hàng hủy kết nối (ví dụ: máy chủ đã chỉ định subprotocol mà khách hàng không cung cấp).
  • Máy chủ WebSocket đột ngột đóng kết nối sau khi hoàn tất thành công việc bắt tay mở.

[...] Cho phép tập lệnh phân biệt các trường hợp này sẽ cho phép tập lệnh thăm dò mạng cục bộ của người dùng để chuẩn bị tấn công.

Trình duyệt cố ý loại bỏ bất kỳ thông tin hữu ích nào theo yêu cầu của thông số kỹ thuật. Các tác giả cụ thể lo ngại rằng việc truy cập thông tin này có thể cho phép một trang web độc hại thu thập thông tin về mạng của bạn, vì vậy họ yêu cầu trình duyệt báo cáo tất cả các lỗi kết nối theo cách không thể phân biệt được. Tuy nhiên,

+0

Đó là thông tin rất hữu ích, mặc dù tôi không thấy lý do tại sao ngoại lệ không bị "bắt". Điều đó dường như phá vỡ khuôn khổ cơ bản của ngôn ngữ. Tôi đoán rằng cách để làm những gì tôi muốn sẽ là xử lý onclose và nhìn vào mã của CloseEvent. – andyhasit

+4

@AndyHasIt Tôi đã thêm đoạn mở đầu về điều đó; Tôi hy vọng nó đủ rõ ràng. Về cơ bản, chúng tôi không thể 'bắt' một lỗi vì chúng tôi đồng bộ thoát khỏi khối 'try' trước khi cố gắng kết nối không đồng bộ gặp lỗi. – apsillers

+0

Làm cho cảm giác hoàn hảo, cảm ơn sự giúp đỡ của bạn. – andyhasit

0

Tôi đã thử tạo fiddle với nó và tôi có thể xem dòng được in.

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

Đó là do một lỗi khác: "Kết nối WebSocket không an toàn có thể không được bắt đầu từ một trang được tải qua HTTPS". – dfreeman

+0

Thật vậy, ví dụ jsfiddle bắt lỗi, nhưng nếu bạn mở bàn điều khiển của bạn và chạy giống như nó không bắt lỗi. Như dfreeman chỉ ra đây là những lỗi khác nhau. – andyhasit

Các vấn đề liên quan