1.0.1 • Published 7 years ago

@reactive-crystal/redux-websocket v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 years ago

Demonstration

Motivation

Doing a lot of research I did not find anything very solid about working with Redux and WebSocket, so I started some tests and came up with some conclusions that helped me get started in this library which controls the connection by a middleware, the state by the reducer and the messages from the server by a protocol handler.

Installing

npm install --save @reactive-crystal/redux-websocket

OR

yarn add @reactive-crystal/redux-websocket

Then, to enable Redux Websocket, use applyMiddleware():

import { createStore, applyMiddleware } from 'redux';
import {middleware as wsMiddleware, createReducer} from '@reactive-crystal/redux-websocket';
import rootReducer from './reducers/index';

// Note: this API requires redux@>=3.1.0
const store = createStore(
  combineReducers({
    ...rootReducer,
    ws: createReducer('ws')
  }),
  applyMiddleware(wsMiddleware)
);

Actions

 import { createActions } from '@reactive-crystal/redux-websocket';
 
 const actions = createActions('ws');

Open

The open action initializes a new connection; If has a previous open connection then closes and open new

  /**
   * Interface used to handle the messages between client and server
   * Ex encode/decode to json or msgpack
   */
  export interface IFilterInterface {
      /** This function is used to encode message */
      encode: (message: any) => any | Promise<any>;
      /** This function is used to decode message */
      decode: (message: MessageEvent) => any | Promise<any>;
      /** Use handlers on JSON RPC calls */
      // useOnRPC?: boolean;
  }
  /**
   * Socket connection configuration
   */
  export interface ISocketOpenConfig {
      /** Websocket Binary type default is blob */
      binaryType?: "blob" | "arraybuffer";
      /** Protocols used by websocket */
      protocols?: string | string[] | undefined;
      /** Handle socket messages ex encode and decode to json */
      filter?: IFilterInterface;
  }
  function open(url: string, config: ISocketOpenConfig):Action

Close()

The close action closes the connection

  function close():Action;

Send

Enqueues data to be transmited.

function send(data: string | ArrayBufferLike | Blob | ArrayBufferView):Action;

attachProtocolHandler

Add a protocol handler to our websocket state

  function attachProtocolHandler(handler: ProtocolHandler, key: string):Action;

detachProtocolHandler

Remove a procol handler from our websocket state

  function attachProtocolHandler(key: string):Action;

ProtocolHandler

Protocols Handlers are functions that receive message, getState function and a dispatcher.

 import { ProtocolHandler } from '@reactive-crystal/redux-websocket';

 type ProtocolHandler = (message: MessageEvent, getState: any, dispatch: (action: any) => void) => void;
import { createActions, ProtocolHandler } from '@reactive-crystal/redux-websocket';
const actions = createActions('ws');
function PongHandler(message: MessageEvent, getState: any, dispatch: (action: any) => void){
    if(message.data == 'PONG'){
      alert('Server says pong');
      this.dispatch({type: 'DO_PING'});
      console.log(this.getState());
    }
}
// Register the PongHandler
store.dispatch(actions.attachProtocolHandler(PongHandler, "PongHandler"))

Reducer state

Working together with the middleware we have the reducer which contains information about the state of the connection and the ProtocolHandler's registered errors etc. See the interface:

interface IWebsocketState {
    error: boolean;
    errorMessage: string | null;
    status: "OPEN" | "OPENING" | "CLOSED" | "CLOSING";
    handlers: {[key: string]: ProtocolHandler} ;
}

Multiple Connection

To use multiple connection just user another name for connection name parameter in createReducer and createActions

import { createStore, applyMiddleware } from 'redux';
import {middleware as wsMiddleware, createReducer, createActions} from '@reactive-crystal/redux-websocket';
import rootReducer from './reducers/index';
 const actionsConn1 = createActions('ws1');
 const actionsConn2 = createActions('ws2');
// Note: this API requires redux@>=3.1.0
const store = createStore(
  combineReducers({
    ...rootReducer,
    ws1: cc('ws1'),
    ws2: createReducer('ws2'),
  }),
  applyMiddleware(wsMiddleware)
);
1.0.1

7 years ago

1.0.0

7 years ago