Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { combineReducers, createStore, Dispatch, Reducer } from 'redux';
- export enum AsyncResultStatus {
- uninitialized = 'uninitialized',
- loading = 'loading',
- success = 'success',
- error = 'error'
- }
- export interface AsyncResultState<T, E> {
- status: AsyncResultStatus;
- timestamp: number;
- error?: E;
- value?: T;
- }
- export class AsyncResultBuilder<T, E> {
- reducer: Reducer<AsyncResultState<T, E>>;
- actionGroup: {
- reset: (dispatch: Dispatch, defaultValue?: boolean) => void;
- start: (dispatch: Dispatch, keepLastValue?: boolean) => void;
- fail: (dispatch: Dispatch, error: E, keepLastValue?: boolean) => void;
- done: (dispatch: Dispatch, value: T) => void;
- };
- constructor(groupName: string, defaultValue?: T, keepLastValue?: boolean) {
- const initState: AsyncResultState<T, E> = {
- status: AsyncResultStatus.uninitialized,
- timestamp: new Date().valueOf(),
- error: undefined,
- value: defaultValue
- };
- this.reducer = (state = initState, action) => {
- switch (action.type) {
- case groupName + '_RESET':
- return {
- status: AsyncResultStatus.uninitialized,
- timestamp: new Date().valueOf(),
- error: undefined,
- value: action.defaultValue || defaultValue
- };
- case groupName + '_START':
- return {
- status: AsyncResultStatus.loading,
- timestamp: new Date().valueOf(),
- error: undefined,
- value: (action.keepLastValue || keepLastValue) ? state.value : undefined
- };
- case groupName + '_FAIL':
- return {
- status: AsyncResultStatus.error,
- timestamp: new Date().valueOf(),
- error: action.error,
- value: (action.keepLastValue || keepLastValue) ? state.value : undefined
- };
- case groupName + '_DONE':
- return {
- status: AsyncResultStatus.success,
- timestamp: new Date().valueOf(),
- error: undefined,
- value: action.value
- };
- default:
- return state;
- }
- };
- this.actionGroup = {
- reset: (dispatch, defaultValue) =>
- dispatch({ type: groupName + '_RESET', defaultValue }),
- start: (dispatch, keepLastValue) =>
- dispatch({ type: groupName + '_START', keepLastValue }),
- fail: (dispatch, error, keepLastValue) =>
- dispatch({ type: groupName + '_FAIL', error, keepLastValue }),
- done: (dispatch, value) =>
- dispatch({ type: groupName + '_DONE', value })
- };
- }
- }
- (function example(): void {
- const fetchProductResultBuilder = new AsyncResultBuilder<string[], Error>('FETCH_PRODUCT');
- // minimal redux setup
- const app = combineReducers({
- fetchProductResult: fetchProductResultBuilder.reducer
- });
- const store = createStore(app);
- // listen to every change in this redux for testing
- store.subscribe(() => {
- console.log(store.getState());
- });
- // simulate async action chain
- fetchProductResultBuilder.actionGroup.start(store.dispatch);
- setTimeout(() => {
- fetchProductResultBuilder.actionGroup.done(store.dispatch, ['Product A', 'Product B']);
- }, 1000);
- })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement