Advertisement
Guest User

Untitled

a guest
Apr 19th, 2019
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.13 KB | None | 0 0
  1. import { combineReducers, createStore, Dispatch, Reducer } from 'redux';
  2.  
  3. export enum AsyncResultStatus {
  4. uninitialized = 'uninitialized',
  5. loading = 'loading',
  6. success = 'success',
  7. error = 'error'
  8. }
  9.  
  10. export interface AsyncResultState<T, E> {
  11. status: AsyncResultStatus;
  12. timestamp: number;
  13. error?: E;
  14. value?: T;
  15. }
  16.  
  17. export class AsyncResultBuilder<T, E> {
  18. reducer: Reducer<AsyncResultState<T, E>>;
  19. actionGroup: {
  20. reset: (dispatch: Dispatch, defaultValue?: boolean) => void;
  21. start: (dispatch: Dispatch, keepLastValue?: boolean) => void;
  22. fail: (dispatch: Dispatch, error: E, keepLastValue?: boolean) => void;
  23. done: (dispatch: Dispatch, value: T) => void;
  24. };
  25.  
  26. constructor(groupName: string, defaultValue?: T, keepLastValue?: boolean) {
  27. const initState: AsyncResultState<T, E> = {
  28. status: AsyncResultStatus.uninitialized,
  29. timestamp: new Date().valueOf(),
  30. error: undefined,
  31. value: defaultValue
  32. };
  33.  
  34. this.reducer = (state = initState, action) => {
  35. switch (action.type) {
  36. case groupName + '_RESET':
  37. return {
  38. status: AsyncResultStatus.uninitialized,
  39. timestamp: new Date().valueOf(),
  40. error: undefined,
  41. value: action.defaultValue || defaultValue
  42. };
  43. case groupName + '_START':
  44. return {
  45. status: AsyncResultStatus.loading,
  46. timestamp: new Date().valueOf(),
  47. error: undefined,
  48. value: (action.keepLastValue || keepLastValue) ? state.value : undefined
  49. };
  50. case groupName + '_FAIL':
  51. return {
  52. status: AsyncResultStatus.error,
  53. timestamp: new Date().valueOf(),
  54. error: action.error,
  55. value: (action.keepLastValue || keepLastValue) ? state.value : undefined
  56. };
  57. case groupName + '_DONE':
  58. return {
  59. status: AsyncResultStatus.success,
  60. timestamp: new Date().valueOf(),
  61. error: undefined,
  62. value: action.value
  63. };
  64. default:
  65. return state;
  66. }
  67. };
  68.  
  69. this.actionGroup = {
  70. reset: (dispatch, defaultValue) =>
  71. dispatch({ type: groupName + '_RESET', defaultValue }),
  72. start: (dispatch, keepLastValue) =>
  73. dispatch({ type: groupName + '_START', keepLastValue }),
  74. fail: (dispatch, error, keepLastValue) =>
  75. dispatch({ type: groupName + '_FAIL', error, keepLastValue }),
  76. done: (dispatch, value) =>
  77. dispatch({ type: groupName + '_DONE', value })
  78. };
  79. }
  80. }
  81.  
  82. (function example(): void {
  83. const fetchProductResultBuilder = new AsyncResultBuilder<string[], Error>('FETCH_PRODUCT');
  84.  
  85. // minimal redux setup
  86. const app = combineReducers({
  87. fetchProductResult: fetchProductResultBuilder.reducer
  88. });
  89. const store = createStore(app);
  90.  
  91. // listen to every change in this redux for testing
  92. store.subscribe(() => {
  93. console.log(store.getState());
  94. });
  95.  
  96. // simulate async action chain
  97. fetchProductResultBuilder.actionGroup.start(store.dispatch);
  98. setTimeout(() => {
  99. fetchProductResultBuilder.actionGroup.done(store.dispatch, ['Product A', 'Product B']);
  100. }, 1000);
  101. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement