client/src/sagas/networkSaga.js
changeset 87 dbcee57de2c6
child 88 2a861fed6bde
equal deleted inserted replaced
86:fa8ef84a1780 87:dbcee57de2c6
       
     1 import * as types from '../constants/actionTypes';
       
     2 import { all, call, fork, race, take, cancelled, put, select } from 'redux-saga/effects'
       
     3 import config from '../config';
       
     4 
       
     5 // Utility function to delay effects
       
     6 function delay(millis) {
       
     7     const promise = new Promise(resolve => {
       
     8         setTimeout(() => resolve(true), millis)
       
     9     });
       
    10     return promise;
       
    11 }
       
    12 
       
    13 function pingServer(client, token) {
       
    14   console.log("PING SERVER", token);
       
    15   if(token) {
       
    16     const timeout = new Promise((resolve, reject) => {
       
    17       setTimeout(reject, config.networkStatusTimeout, 'request timed out');
       
    18     });
       
    19     return Promise
       
    20       .race([timeout, client.post('/api/auth/refresh/', { token })]);
       
    21   } else {
       
    22     return Promise.reject({ error: 'No token in the store'})
       
    23   }
       
    24 }
       
    25 
       
    26 // Fetch data every 20 seconds
       
    27 function* pollData(context) {
       
    28   try {
       
    29     yield call(delay, config.networkStatusInterval);
       
    30     const token = yield select(state => state.token);
       
    31     const res = yield pingServer(context.client, token);
       
    32     yield call(context.callback, true);
       
    33     yield put({
       
    34       type: types.AUTH_STORE_TOKEN_ASYNC,
       
    35       token: res.token,
       
    36     });
       
    37   } catch (error) {
       
    38     yield call(context.callback, false);
       
    39     // if the error is that there is no token, then we know we have to wait for a login
       
    40     if(error.error && error.error === 'No token in the store') {
       
    41       yield take(types.AUTH_LOGIN_SUCCESS);
       
    42     }
       
    43   } finally {
       
    44     if (yield cancelled()) {
       
    45       // pollDate cancelled
       
    46       // if there is a token : this was a LOGIN, set status to ok
       
    47       // if there is no token : this was a LOGOUT, set status to ko and wait for login
       
    48       const token = yield select(state => state.token);
       
    49       if(token) {
       
    50         yield call(context.callback, true);
       
    51       } else {
       
    52         yield call(context.callback, false);
       
    53         yield take(types.AUTH_LOGIN_SUCCESS);
       
    54       }
       
    55     }
       
    56   }
       
    57 }
       
    58 
       
    59 // Wait for successful response, then fire another request
       
    60 // Cancel polling if user logs out or log in
       
    61 function* watchPollData(context) {
       
    62   while (true) {
       
    63     yield race([
       
    64       call(pollData, context),
       
    65       take(types.AUTH_LOGOUT),
       
    66       take(types.AUTH_LOGIN_SUCCESS)
       
    67     ]);
       
    68   }
       
    69 }
       
    70 
       
    71 // Daemonize tasks in parallel
       
    72 export default function* root(baseContext) {
       
    73   const actionRes = yield take(types.OFFLINE_CONFIG_INITIALIZED);
       
    74   const context = {...baseContext, ...actionRes.additionalContext};
       
    75   yield all([
       
    76     fork(watchPollData, context)
       
    77     // other watchers here
       
    78   ]);
       
    79 }