De Giovanni
De Giovanni

Reputation: 321

Websocket as promised for redux

How can I transform this websocket as promised in redux ? I wanted to use this library https://www.npmjs.com/package/websocket-as-promised , but I don't know how to implement this in my weksocket.

I need your help PLEASEEE.

This websocket for redux has been created by "exec64" and it's functional in my application but I want that it return a promise.

source: https://exec64.co.uk/blog/websockets_with_redux/

My middleware

import actions from './actions'

const socketMiddleware = (function(){ 
  var socket = null;

  const onOpen = (ws,store,token) => evt => {
    //Send a handshake, or authenticate with remote end

    //Tell the store we're connected
    store.dispatch(actions.connected());
  }

  const onClose = (ws,store) => evt => {
    //Tell the store we've disconnected
    store.dispatch(actions.disconnected());
  }

  const onMessage = (ws,store) => evt => {
    //Parse the JSON message received on the websocket
    var msg = JSON.parse(evt.data);
    switch(msg.type) {
      case "CHAT_MESSAGE":
        //Dispatch an action that adds the received message to our state
        store.dispatch(actions.messageReceived(msg));
        break;
      default:
        console.log("Received unknown message type: '" + msg.type + "'");
        break;
    }
  }

  return store => next => action => {
    switch(action.type) {

      //The user wants us to connect
      case 'CONNECT':
        //Start a new connection to the server
        if(socket != null) {
          socket.close();
        }
        //Send an action that shows a "connecting..." status for now
        store.dispatch(actions.connecting());

        //Attempt to connect (we could send a 'failed' action on error)
        socket = new WebSocket(action.url);
        socket.onmessage = onMessage(socket,store);
        socket.onclose = onClose(socket,store);
        socket.onopen = onOpen(socket,store,action.token);

        break;

      //The user wants us to disconnect
      case 'DISCONNECT':
        if(socket != null) {
          socket.close();
        }
        socket = null;

        //Set our state to disconnected
        store.dispatch(actions.disconnected());
        break;

      //Send the 'SEND_MESSAGE' action down the websocket to the server
      case 'SEND_CHAT_MESSAGE':
        socket.send(JSON.stringify(action));
        break;

      //This action is irrelevant to us, pass it on to the next middleware
      default:
        return next(action);
    }
  }

})();

export default socketMiddleware

My Action types

export const WS_CONNECTING = 'WS_CONNECTING'
export const WS_CONNECTED = 'WS_CONNECTED'
export const WS_DISCONNECTED = 'WS_DISCONNECTED'
export const WS_CONNECT = 'WS_CONNECT'
export const WS_DISCONNECT = 'WS_DISCONNECT

My app Actions (actions creator)

import * as types from './actionsTypes'
export function wsConnecting() {
  return {
    type: types.WS_CONNECTING
  }
}

export function wsConnected() {
  return {
    type: types.WS_CONNECTED
  }
}

export function wsDisconnected(reason = "No reason") {
  return {
    type: types.WS_DISCONNECTED,
    reason
  }
}

export function wsConnect(url) {
  return {
    type: types.WS_CONNECT,
    url: url
  }
}

And my reducer

    import * as types from '../actions/actionsTypes'

    function appReducers(state = [], action) {
      switch (action.type) {
        case types.WS_CONNECTING:      
          return Object.assign({}, state, { status: types.WS_CONNECTING });
        case types.WS_CONNECTED:      
          return Object.assign({}, state, { status: types.WS_CONNECTED });
        case types.WS_DISCONNECTED:      
          return Object.assign({}, state, { status: types.WS_DISCONNECTED });
        default:
          return state
      }
    }

    export default appReducers

I tried to install and import the library websocket-as-promised (https://www.npmjs.com/package/websocket-as-promised), then I replaced just this code in my websocket :

socket = new WebSocket(action.url);

**By this but it not functional **

socket = new WebSocketAsPromised(action.url);

Upvotes: 1

Views: 1014

Answers (2)

Compulim
Compulim

Reputation: 1168

You can also look at redux-websocket-bridge, which can unfold all Web Socket messages into your Redux store, and relay all Redux actions into Web Socket. It would save you some work on your CHAT_MESSAGE and SEND_CHAT_MESSAGE.

On top of unfold/relay actions, it also expose Web Socket events thru as Redux actions.

Upvotes: 0

De Giovanni
De Giovanni

Reputation: 321

Thanks, I found the solution I wanted. I share my custom websocket for those who want a websocket as promised with redux:

import actions from './actions'
import WebSocketAsPromised from 'websocket-as-promised';

const socketMiddleware = (function() {
    var socket = null;

    const onOpen = (ws, store, token) => {
        //Send a handshake, or authenticate with remote end

        //Tell the store we're connected
        store.dispatch(actions.connected());
    }

    const onClose = (ws, store) => {
        //Tell the store we've disconnected
        store.dispatch(actions.disconnected());
    }

    const onMessage = (msg, store) => {
        //Parse the JSON message received on the websocket
        var msg = msg;
        switch (msg.type) {
            case "CHAT_MESSAGE":
                //Dispatch an action that adds the received message to our state
                store.dispatch(actions.messageReceived(msg));
                break;
            default:
                console.log("Received unknown message type: '" + msg.type + "'");
                break;
        }
    }

    return store => next => action => {
        switch (action.type) {

            //The user wants us to connect
            case 'CONNECT':
                //Start a new connection to the server
                if (socket != null) {
                    socket.close();
                }
                //Send an action that shows a "connecting..." status for now
                store.dispatch(actions.connecting());

                //Attempt to connect (we could send a 'failed' action on error)
                socket = new WebSocketAsPromised(action.url);
                socket.onMessage.addListener((data, jsonData) => onMessage(jsonData, store))
                socket.onClose.addListener(() => onClose(socket, store))
                socket.open()
                      .then(() => {onOpen(socket, store, action.token)})
                break;

                //The user wants us to disconnect
            case 'DISCONNECT':
                if (socket != null) {
                    socket.close();
                }
                socket = null;

                //Set our state to disconnected
                store.dispatch(actions.disconnected());
                break;

                //Send the 'SEND_MESSAGE' action down the websocket to the server
            case 'SEND_CHAT_MESSAGE':
                socket.send(JSON.stringify(action));
                break;

                //This action is irrelevant to us, pass it on to the next middleware
            default:
                return next(action);
        }
    }

})();

export default socketMiddleware

Upvotes: 1

Related Questions