Django 通道和反应错误:WebSocket 连接到“ws://localhost:8000/myURL”失败:WebSocket 在建立连接之前关闭

ill*_*ens 3 javascript python websocket reactjs django-channels

首先,我还不知道问题出在前端还是后端,但看来后端的可能性更大。

我使用 django-channels 构建了一个 Django 应用程序,通过 websocket 连接将数据包发送到前端react.js SPA;我之前还构建了一个简单的 vanilla-javascript 客户端(由 Django 提供),并且它没有这个问题。

问题是,我在打开时在 Firefox 控制台中收到此错误(它们随机切换位置,表明它们同时发生):

Firefox can't establish a connection to the server at ws://localhost:8000/ws/XY_Broadcast/. App.jsx:32
The connection to ws://localhost:8000/ws/XY_Broadcast/ was interrupted while the page was loading. App.jsx:32
Run Code Online (Sandbox Code Playgroud)

使用 Brave 浏览器(基于 Chromium),我得到这个:

(warning) App.jsx:69 WebSocket connection to 'ws://localhost:8000/ws/XY_Broadcast' failed: WebSocket is closed before the connection is established.
(error)App.jsx:38 WebSocket connection to 'ws://localhost:8000/ws/XY_Broadcast' failed: 
Run Code Online (Sandbox Code Playgroud)

但奇怪的是,我的页面似乎可以打开并工作 - 它会在打开时和在一段时间后接收数据时打印消息。 Websocket 错误代码为 1006。

我尝试过的:

  • 一些用于测试 websocket 连接的浏览器扩展 - 它们都不会连接(这就是为什么我认为这是一个后端问题)。
  • 我也不认为问题出在 CORS 上 - 我之前遇到过问题(我的前端应用程序显示不会显示从后端的 HTTP URL 获取的图像),并且我有一个扩展程序可以将其打开在浏览器中打开/关闭 - 它不会影响任何东西。
  • 我尝试将ASGI_APPLICATIONDjango 设置切换为myproject.asgi.applicationdjango-channels 文档中提到的,但它没有帮助,所以我将其设置回myApp.routing.application
  • 我尝试使用 daphne 而不是运行该项目runserver,在我的 docker-compose 文件中,我有daphne -b 0.0.0.0 -p 8000 some_demo_django.asgi:application. React 页面打开并显示从后端获取的图像,但错误仍然存​​在。此外,虽然旧的(普通 JS 页面)不会加载,但我得到了500 Internal Server Error Daphne HTTP processing error来自后端的以下回溯:
  File "/usr/local/lib/python3.10/site-packages/daphne/http_protocol.py", line 163, in process
    self.application_queue = yield maybeDeferred(
TypeError: ASGIHandler.__call__() missing 2 required positional arguments: 'receive' and 'send'

172.19.0.1:41728 - - [13/Oct/2022:00:06:48] "GET /dev_td/" 500 452
172.19.0.1:41718 - - [13/Oct/2022:00:06:49] "WSDISCONNECT /ws/XY_Broadcast" - -
2022-10-13 00:06:49,429 ERROR    Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/daphne/http_protocol.py", line 163, in process
    self.application_queue = yield maybeDeferred(
TypeError: ASGIHandler.__call__() missing 2 required positional arguments: 'receive' and 'send'
172.19.0.1:41728 - - [13/Oct/2022:00:06:49] "GET /dev_td/" 500 452
2022-10-13 00:06:55,721 ERROR    Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/daphne/http_protocol.py", line 163, in process
    self.application_queue = yield maybeDeferred(
TypeError: ASGIHandler.__call__() missing 2 required positional arguments: 'receive' and 'send'
Run Code Online (Sandbox Code Playgroud)

反应代码是:

export default function App() {
  const [messages, setMessages] = useState([]);
  useEffect(() => {
    const ws = new WebSocket('ws://localhost:8000/ws/XY_Broadcast/');
    ws.onopen = (event) => {
      console.log(event.data)
      console.log('ws opened')
    };
    ws.onmessage = function (event) {
        console.log(event.data)
    };
    ws.onclose = function(event){
      console.log("closed, code is:",event.code)
    };
    return () => ws.close();
  }, []);
Run Code Online (Sandbox Code Playgroud)

之前构建的普通 JavaScript 客户端代码是:

  var XY_Broadcast = new WebSocket(
    'ws://' + window.location.host + '/ws/XY_Broadcast/');

  XY_Broadcast.onmessage = function(e) {
    let loc_data = JSON.parse(e.data);

  ... (my logic) 

  XY_Broadcast.onclose = function (e) {
    console.error('XY_Broadcast socket connection closed');
    for(var i=0; i<e.length; i++) {
      console.log(e)
    }
  };

Run Code Online (Sandbox Code Playgroud)

我浏览了在互联网上可以找到的所有答案,并与公司的高级开发人员讨论了这个问题,但没有成功。

mon*_*nim 5

当您尝试在 WebSocket 连接ws.close()有机会实际连接之前关闭它时,就会发生这种情况。

尝试更改 useEffect 清理功能:

return () => ws.close();
Run Code Online (Sandbox Code Playgroud)

到 :

return () => {
            if (socket.readyState === 1) { 
                socket.close();
            }
Run Code Online (Sandbox Code Playgroud)