How to wait for a WebSocket's readyState to change

后端 未结 9 2352
梦如初夏
梦如初夏 2020-11-30 00:54

I\'m trying to implement a WebSocket with a fallback to polling. If the WebSocket connection succeeds, readyState becomes 1, but if it fails, readyState

9条回答
  •  天涯浪人
    2020-11-30 01:08

    tl;dr

    A simple proxy wrapper to add state event to WebSocket which will be emitted when its readyState changes:

    const WebSocketProxy = new Proxy(WebSocket, {
        construct: function(target, args) {
            // create WebSocket instance
            const instance = new target(...args);
    
            //internal function to dispatch 'state' event when readyState changed
            function _dispatchStateChangedEvent() {
                instance.dispatchEvent(new Event('state'));
                if (instance.onstate && typeof instance.onstate === 'function') {
                    instance.onstate();
                }
            }
    
            //dispatch event immediately after websocket was initiated
            //obviously it will be CONNECTING event
            setTimeout(function () {
                _dispatchStateChangedEvent();
            }, 0);
    
            // WebSocket "onopen" handler
            const openHandler = () => {
                _dispatchStateChangedEvent();
            };
    
            // WebSocket "onclose" handler
            const closeHandler = () => {
                _dispatchStateChangedEvent();
                instance.removeEventListener('open', openHandler);
                instance.removeEventListener('close', closeHandler);
            };
    
            // add event listeners
            instance.addEventListener('open', openHandler);
            instance.addEventListener('close', closeHandler);
    
            return instance;
        }
    });
    

    A long explanation:

    You can use a Proxy object to monitor inner WebSocket state.

    This is a good article which explains how to do it Debugging WebSockets using JS Proxy Object

    And here is an example of code snippet from the article above in case the site won't be available in the future:

    // proxy the window.WebSocket object
    var WebSocketProxy = new Proxy(window.WebSocket, {  
      construct: function(target, args) {
        // create WebSocket instance
        const instance = new target(...args);
    
        // WebSocket "onopen" handler
        const openHandler = (event) => {
          console.log('Open', event);
        };
    
        // WebSocket "onmessage" handler
        const messageHandler = (event) => {
          console.log('Message', event);
        };
    
        // WebSocket "onclose" handler
        const closeHandler = (event) => {
          console.log('Close', event);
          // remove event listeners
          instance.removeEventListener('open', openHandler);
          instance.removeEventListener('message', messageHandler);
          instance.removeEventListener('close', closeHandler);
        };  
    
        // add event listeners
        instance.addEventListener('open', openHandler);
        instance.addEventListener('message', messageHandler);
        instance.addEventListener('close', closeHandler);
    
        // proxy the WebSocket.send() function
        const sendProxy = new Proxy(instance.send, {
          apply: function(target, thisArg, args) {
            console.log('Send', args);
            target.apply(thisArg, args);
          }
        });
    
        // replace the native send function with the proxy
        instance.send = sendProxy;
    
        // return the WebSocket instance
        return instance;
      }
    });
    
    // replace the native WebSocket with the proxy
    window.WebSocket = WebSocketProxy; 
    

提交回复
热议问题