Advertisement
jazzmonster

Websocket в React-Redux на Saga

Nov 24th, 2017
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { all, takeEvery, take, call, put, select } from 'redux-saga/effects';
  2. import { eventChannel, delay } from 'redux-saga';
  3. import { getToken } from './selectors';
  4.  
  5. import { ERROR } from '../constants/genericTypes';
  6.  
  7. import { WEBSOCKET_ONERROR, // ERRORS
  8.          WEBSOCKET_ERROR_PARSING,
  9.          UNKNOWN_TYPE_OF_INCOMING_ACTION } from '../constants/errors';
  10.  
  11. import { NEW_TOKEN, // INCOMING ACTIONS
  12.          CURRENT_TOKEN_IS_OK,
  13.          USERINFO_RECEIVED,
  14.          UNAUTHORIZED,
  15.          LOG } from '../constants/actionTypes';
  16.  
  17. import { WEBSOCKET_ONOPEN,
  18.          TOKEN_REQUESTED, // UPCOMING ACTIONS
  19.          SIGN_OUT,
  20.          USERINFO_REQUESTED,
  21.         } from '../constants/actionTypes';
  22.  
  23. const createWebSocketConnection = () => new WebSocket(wsURL('/websocket/'))
  24.  
  25. export default function* websocketSagas() {
  26.     const socket: any = yield call(createWebSocketConnection)
  27.   yield all([
  28.     watchIncoming(socket),
  29.     watchUpcoming(socket)
  30.   ])
  31. }
  32.  
  33. function incomingWebsocketChannel(socket: any) {
  34.   return eventChannel( emitter => {
  35.     socket.onopen = () => {
  36.         return emitter({ type: WEBSOCKET_ONOPEN })
  37.     }
  38.     socket.onerror = (error: any) => {
  39.         return emitter({ type: ERROR, error: WEBSOCKET_ONERROR, meta: error })
  40.     }
  41.       socket.onmessage = (frame: any) => {
  42.         let action = null
  43.         try {
  44.             action = JSON.parse(frame.data)
  45.         } catch(frame) {
  46.             return emitter({ type: ERROR, error: WEBSOCKET_ERROR_PARSING, meta: frame.data })
  47.         }
  48.         if(action) {
  49.             switch (action.type) {
  50.                 case "pong":
  51.                     return emitter(action)
  52.                 case NEW_TOKEN:
  53.                     return emitter(action)
  54.                 case CURRENT_TOKEN_IS_OK:
  55.                     return emitter(action)
  56.                 case USERINFO_RECEIVED:
  57.                     return emitter(action)
  58.                 case UNAUTHORIZED:
  59.                     return emitter(action)
  60.                 case LOG:
  61.                     return emitter(action)
  62.                 default:
  63.                     return emitter({ type: ERROR, error: UNKNOWN_TYPE_OF_INCOMING_ACTION, meta: action })
  64.             }
  65.         }
  66.     }
  67.     // unsubscribe function
  68.     return () => {
  69.         console.log('Socket off')
  70.     }
  71.   })
  72. }
  73.  
  74. function* watchIncoming(socket: any) {
  75.     const channel = yield call(incomingWebsocketChannel, socket)
  76.     while (true) {
  77.         const action = yield take(channel)
  78.         yield put(action)
  79.     }
  80. }
  81.  
  82. function* watchUpcoming(socket: any) {
  83.   yield takeEvery(WEBSOCKET_ONOPEN, open, socket)
  84.   yield takeEvery("pong", pong, socket)
  85.   yield takeEvery("ping", send, socket)
  86.   yield takeEvery(TOKEN_REQUESTED, send, socket)
  87.   yield takeEvery(USERINFO_REQUESTED, send, socket)
  88.   yield takeEvery(SIGN_OUT, send, socket)
  89. }
  90.  
  91. function* open(socket: any) {
  92.   yield put({ type: TOKEN_REQUESTED })
  93.   yield delay(1000)
  94.   yield put({ type: "ping" })
  95. }
  96.  
  97. function* pong(socket: any) {
  98.   yield delay(15000)
  99.   yield socket.send(JSON.stringify({ type: "ping" }))
  100. }
  101.  
  102. function* send(socket: any, action: any) {
  103.   action.token = yield select(getToken)
  104.   if(!action.server_meta)
  105.     yield socket.send(JSON.stringify(action))
  106. }
  107.  
  108. const wsURL = (path: any) => { // Thx stackoverflow.com for this fun.
  109.   var protocol = (window.location.protocol === 'https:') ? 'wss://' : 'ws://'
  110.   var url = protocol + window.location.host
  111.   if(window.location.hostname === 'localhost') {
  112.         url += '/' + window.location.pathname.split('/')[1]
  113.   }
  114.   return url + path
  115. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement