Advertisement
Guest User

Untitled

a guest
Feb 13th, 2016
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.69 KB | None | 0 0
  1. import { createStore, applyMiddleware } from 'redux';
  2. import { Observable, Subject } from 'rxjs';
  3.  
  4. const api = type => {
  5. console.log(`calling API ${type}`);
  6. return new Promise(res => setTimeout(() => res(), 500));
  7. };
  8.  
  9. const actionOrder = (actions, order) => actions.every((action, index) => action.type === order[index]);
  10. const actionPredicate = actions => filterableAction => actions.some(action => action === filterableAction.type);
  11. const buildAction = type => () => ({ type });
  12.  
  13. const AUTH_EXPIRATION = 1000;
  14.  
  15. const LOG_OUT_ACTIONS_ORDER = ['LOG_IN', 'LOGGED_IN', 'LOG_OUT'];
  16.  
  17. // User clicked the log in button,
  18. // call the API and respond either success or failure
  19. const authGetTokenSaga = iterable => iterable
  20. .filter(actionPredicate(['LOG_IN']))
  21. .flatMap(() => Observable
  22. .fromPromise(api('get token'))
  23. .map(buildAction('LOGGED_IN'))
  24. .catch(reason => Observable.of({type: 'LOG_IN_FAILURE', payload: reason})));
  25.  
  26. // After the user is successfuly logged in,
  27. // let's schedule an infinite interval stream
  28. // which can be interrupted either by LOG_OUT
  29. // or failure in refreshing (TOKEN_REFRESHING_FAILED)
  30. const authRefreshTokenSaga = iterable => iterable
  31. .filter(actionPredicate(['LOGGED_IN']))
  32. .flatMap(() => Observable
  33. .interval(AUTH_EXPIRATION)
  34. .flatMap(() => Observable
  35. .fromPromise(api('refresh token'))
  36. .map(buildAction('TOKEN_REFRESHED'))
  37. .catch(() => Observable.of(
  38. {type: 'TOKEN_REFRESHING_FAILED'}))
  39. ))
  40. .takeUntil(iterable.filter(actionPredicate(['LOG_OUT', 'TOKEN_REFRESHING_FAILED'])));
  41.  
  42. // Observe all the actions in specific order
  43. // to determine whether user wants to log out
  44. const authHandleLogOutSaga = iterable => iterable
  45. .filter(filteringAction => [...LOG_OUT_ACTIONS_ORDER, 'TOKEN_REFRESHING_FAILED']
  46. .some(action => action === filteringAction.type))
  47. .bufferCount(LOG_OUT_ACTIONS_ORDER.length)
  48. .filter(actions => actionOrder(actions, LOG_OUT_ACTIONS_ORDER))
  49. .flatMap(() => Observable
  50. .fromPromise(api('log out'))
  51. .map(buildAction('LOGGED_OUT')));
  52.  
  53.  
  54. const authSaga = iterable => Observable.merge(
  55. authGetTokenSaga(iterable),
  56. authRefreshTokenSaga(iterable),
  57. authHandleLogOutSaga(iterable)
  58. );
  59.  
  60. const sagaMiddleware = saga => {
  61. const subject = new Subject();
  62.  
  63. return store => {
  64. saga(subject).subscribe(dispatchable => store.dispatch(dispatchable));
  65.  
  66. return next => action => {
  67. next(action);
  68. subject.next(action, store.getState());
  69. };
  70. };
  71. };
  72.  
  73. const storeFactory = applyMiddleware(sagaMiddleware(authSaga))(createStore);
  74.  
  75. const store = storeFactory((appState, action) => {
  76. console.log(action);
  77. return appState;
  78. });
  79.  
  80. store.dispatch({type: 'LOG_IN'});
  81. setTimeout(() => {
  82. store.dispatch({type: 'LOG_OUT'});
  83. }, 10000);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement