未捕获的 InvalidStateError:无法在“WebSocket”上执行“发送”:

Posted

技术标签:

【中文标题】未捕获的 InvalidStateError:无法在“WebSocket”上执行“发送”:【英文标题】:Uncaught InvalidStateError: Failed to execute 'send' on 'WebSocket': 【发布时间】:2015-03-20 01:14:56 【问题描述】:

我正在尝试运行此代码:

function smConnect() 
  ws = new WebSocket('ws://127.0.0.1:1805/');
  delete ws.URL;

  ws.onopen = function(response) ;
  ws.onmessage = function(response) ;
  ws.onclose = function(response) ;
  ws.onerror = function(error) ;


smConnect();
ws.send('message', 'hi');

但它返回给我这个错误:

仍处于 CONNECTING 状态。

可能是什么问题?

【问题讨论】:

onopen 处理程序内部运行 send。或者,在 smConnect 上定义自己的 send(),并缓冲直到 ws.readyState==1 @dandavis 我需要用完,有什么办法吗? @dandavis 我有点外行,是要给我看吗? 【参考方案1】:

您可以这样做,它添加了一些日志记录,发送您可以在构造函数之外处理的信息,并且您还可以在自己的命名空间中抽象出 SocketWrapper(好的,是的,它现在在窗口中:))

您可以检查开发工具(大多数浏览器中的 F12)以查看日志/错误中发生的情况,例如:这里会引发错误,因为没有可用的套接字:)

并且您不需要为所有事件提供值,只需为您需要的事件(您的案例 onopen + 可能 onmessage?)

(在定义的回调中,这将指向套接字,而不是 SocketWrapper,SocketWrapper 也不提供 ws 变量,它是私有的,但我猜应该这样做)

SocketWrapper 上有一个 send 方法,当你发送到一个关闭的流时会抛出一个错误,但如果它还没有打开,它会将消息排队,直到它被打开,然后清空队列到websocket(所以从某种意义上说,你不需要设置 onopen 回调,只需使用 send 方法添加它就可以了;)

(function(nameSpace) 
  function createMethod(method, options, stateCallback) 
    var that = this;
    this[method] = function() 
      if (stateCallback && stateCallback.apply) 
        stateCallback(method);
      
      console.info(method);
      if (options[method] && options[method].apply) 
        options[method].apply(that, arguments);
      
    ;
  

  function SocketWrapper(options) 
    var ws,
      events = ['onopen', 'onmessage', 'onclose', 'onerror'],
      i, len, prop = 
        opened: false,
        closed: false,
        error: false
      ,
      method;

    if (typeof options === 'undefined' || !options) 
      throw 'ArgumentException: please add default constructor options';
    
    
    this.queue = [];
    
    this.onEventTrigger = function(eventName) 
      var i, len;
      if (eventName === 'onopen') 
        prop.opened = true;
        prop.closed = false;
        // openend send queue
        if (this.queue.length > 0) 
          for (i = this.queue.length; --i >= 0;) 
            this.send.apply(this, this.queue[0]);
            this.queue.splice(0, 1);
          
        
      
      if (eventName === 'onerror') 
        prop.error = true;
      
      if (eventName === 'onclosed') 
        prop.opened = false;
        prop.closed = true;
      
    ;

    this.init = function() 
      var cb = this.onEventTrigger.bind(this);
      ws = new WebSocket(options.url);

      for (i = 0; i < events.length; i++) 
        method = events[i];
        createMethod.apply(ws, [method, options, cb]);
      
    ;

    this.send = function() 
      if (prop.closed) 
        throw 'InvalidOperation: Cannot send messages to a closed Websocket!';
      
      if (!prop.opened) 
        this.queue.push(arguments);
       else 
        ws.send.apply(ws, arguments);
      
    ;
    
    this.init();
    return this;
  

  window.SocketWrapper = SocketWrapper;
(window));

var socket = new window.SocketWrapper(
  url: 'ws://127.0.0.1:1805',
  onopen: function() 
    this.send('message', 'hi');
  ,
  onmessage: function() 
    console.log(arguments);
  ,
  onclose: function() 
    socket = null;
  ,
  onerror: function() 
    console.log('error occured, oh no!');
    console.error(arguments);
  
);
socket.send('i am message send to soon, but since i check the state of the ws object, i will be queued and send when appropriate');

【讨论】:

以上是关于未捕获的 InvalidStateError:无法在“WebSocket”上执行“发送”:的主要内容,如果未能解决你的问题,请参考以下文章

未捕获的 InvalidStateError:无法在“IDBDatabase”上执行“事务”:版本更改事务正在运行

Java Server,html客户端,无法向服务器发送消息

未捕获的类型错误:无法读取未定义的属性“区域”?

如何在应用程序加载期间捕获“未捕获的类型错误:无法读取未定义的属性‘isModel’?

未捕获的类型错误:无法读取未定义的属性 toLowerCase

错误:`未捕获(承诺中)类型错误:无法读取未定义的属性'doc'`