【问题标题】:WebSocket, even after firing onopen event, still in CONNECTING stateWebSocket,即使在触发 onopen 事件后,仍处于 CONNECTING 状态
【发布时间】:2017-11-08 13:24:42
【问题描述】:

即使在 onconnect 之后尝试,WebSocket 发送方法也会抛出异常。 并非总是如此,但很多时候我会在控制台中看到记录的异常。

这是打字稿代码:-

  open() {
    if ('WebSocket' in window) {
      this.ws = new WebSocket(ApiUrls.Socket(''));
      this.ws.onopen = () => {
        const authentication = {
          msgType : 'Authenticate',
          data : {
            token : localStorage.getItem('authToken')
          }
        }
        this.ws.send(JSON.stringify(authentication));
      };

      this.ws.onmessage = (evt) => {
        // console.log(evt);
        this.parseMessage(evt.data);
      };

      this.ws.onclose = () => {
        this.connected = false;
        // console.log('retrying connection with server');
        if (localStorage.getItem('authToken')) {
          this.reconnectTimeout = setTimeout(this.open.bind(this), 1000);
        }
      };
    } else {
      alert('WebSocket NOT supported by your Browser!');
    }
  }

控制台异常:-

ERROR DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
    at WebSocket.ws.onopen [as __zone_symbol__ON_PROPERTYopen] (http://localhost:4200/main.bundle.js:5586:26)
    at WebSocket.wrapFn (http://localhost:4200/polyfills.bundle.js:3711:39)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.bundle.js:2970:31)
    at Object.onInvokeTask (http://localhost:4200/vendor.bundle.js:87677:33)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.bundle.js:2969:36)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (http://localhost:4200/polyfills.bundle.js:2737:47)
    at ZoneTask.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.bundle.js:3044:34)
    at invokeTask (http://localhost:4200/polyfills.bundle.js:4085:14)
    at WebSocket.globalZoneAwareCallback (http://localhost:4200/polyfills.bundle.js:4111:17)

太冗长了,但关注的消息是,ERROR DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state. at WebSocket.ws.onopen [as __zone_symbol__ON_PROPERTYopen]

【问题讨论】:

  • 报错信息已经很明显为什么会崩溃,不知道你为什么想不通
  • @Dummy 因为我还能做什么,我只是在连接打开后发送一条消息,为什么它仍然处于连接状态我无法弄清楚

标签: javascript typescript websocket


【解决方案1】:

这会在 open 方法被调用两次时中断。在这种情况下, ws 属性将被仍处于连接状态的新 Websocket 覆盖。然后在 onopen 处理程序(异步)中使用了错误的 WebSocket。

const local_websocket = new WebSocket(ApiUrls.Socket(''));
this.ws = local_websocket;
this.ws.onopen = () => {
    const authentication = {
        msgType : 'Authenticate',
        data : {
            token : localStorage.getItem('authToken')
        }
    }
    local_websocket.send(JSON.stringify(authentication));
}; 

【讨论】:

  • 所以基本上我必须确定我是否因任何错误而打开套接字两次
  • 或者您至少可以确保在本地范围的变量上调用发送。我已经更新了我的答案。
  • 好的,谢谢!
  • 这解决了我的问题。
【解决方案2】:

我发现这似乎有帮助:

this.ws.onopen = (e) => {
  // Not sure if the following line is necessary but doesn't hurt
  if (e.target.readyState !== WebSocket.OPEN) return;
  const authentication = {
    msgType : 'Authenticate',
    data : {
      token : localStorage.getItem('authToken')
    }
  }

  // Here's the key: use the websocket instance that triggered the onopen event
  e.target.send(JSON.stringify(authentication));
}

不同之处在于您使用的是触发 onopen 事件的 websocket 实例,而不是存在于您的 this.ws 变量中的实例,因为在此期间 this.ws 可能已经发生了变化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多