Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to mark controller's method as "blocking"?! #11

Open
plandem opened this issue Feb 2, 2017 · 2 comments
Open

how to mark controller's method as "blocking"?! #11

plandem opened this issue Feb 2, 2017 · 2 comments

Comments

@plandem
Copy link

plandem commented Feb 2, 2017

Required:
somehow inside of controller without a lot of boilerplate code to get next: at begin of method dispatch action with promise for promise-middleware, that will be resolved/rejected at the end of method.

Recap:

  1. at begin of method set some redux state to true
  2. at end of method set same redux state to false
  3. at error do same as at (2)

In most cases it's common loading flag (e.g. API requests) to make UI to response changes of state (e.g. block/unblock controls).

Right now I'm doing it like this, but not sure that it's good way, maybe I miss something:

helper:

const blocking = (type, method, dispatch) => (...args)  => {
	return dispatch({ type, payload: new Promise((resolve, reject) => {
		try {
			resolve(method(...args));
		} catch (e) {
			reject(e);
		}
	})});
};

generators with marked onLogin as blocking:

const generators = {
	*initialize() {
		const { dispatch } = yield getProps;

		this.onLogin = blocking(types.APP_PREFIX, this.onLogin, dispatch);

		yield this.userInfo(true, '/');
	},

	*onSiderCollapse() {
		const { dispatch } = yield getProps;
		dispatch(actions.siderCollapse());
	},

	*onLogin(params) {
		const { dispatch } = yield getProps;

			try {
				yield api.login(params);
				yield this.userInfo(false, '/');
			} catch(e) {
				dispatch(error(e)),
				dispatch(auth.reset());
			}
	},

	*onLogout() {
		const { dispatch } = yield getProps;

		try {
			yield api.logout();
		} catch(e) {
		}

		dispatch(auth.reset());
		dispatch(navigate('/'));
	},

	*userInfo(silent = false, returnUrl) {
		const { dispatch, route } = yield getProps;

		try {
			dispatch(auth.request());
			const identity = yield api.fetchCurrrentUser();
			dispatch(auth.receive(identity));

			//if route has url to return, then use it
			let redirect = route && route.query && route.query.return;
			if(!redirect) {
				redirect = returnUrl;
			}

			if(redirect) {
				dispatch(navigate(redirect));
			}
		} catch(e) {
			console.log(e);

			if(!silent) {
				dispatch(error(e));
			}

			dispatch(auth.reset());
			dispatch(navigate('/'));
		}
	}
};

I need it for my reducer, e.g.:

import typeToReducer from 'type-to-reducer';
import * as loading from '../../utils/loading';
import types from './actions';

const initialState = {
	checking: false,
	siderCollapsed: false,
};

const app = typeToReducer({
	[types.SIDER_COLLAPSE]: (state, action) => ({ ...state, siderCollapsed: !state.siderCollapsed }),
	[types.APP_PREFIX]: loading.reducers('checking'),
}, initialState);

export default app;

utils is like this:

export const promiseTypeSuffixes = ['pending', 'fulfilled', 'rejected'];

export const reducers = (key, suffixes = promiseTypeSuffixes) => {
	const reducers = { };
	suffixes.forEach((suffix, i) => reducers[suffix] = (state, action) => ({ ...state, [key]: !i }));
	return reducers;
};
@plandem plandem changed the title how to mark controller's action as "blocking"?! how to mark controller's method as "blocking"?! Feb 2, 2017
@acjay
Copy link
Contributor

acjay commented Mar 1, 2017

I'm not 100% sure what you're going for, but the idea of RRC was to prevent the need for async middleware.

Is the issue that you're trying to essentially apply a decorator (blocking) to a controller method, but that decorator needs a reference to dispatch, but you can only get a handle to it in initialize? Would it also be possible to make blocking a controller generator method?

@plandem
Copy link
Author

plandem commented Mar 1, 2017

in two words, I need to decrease the number of boilerplate code for next behavior:

  1. at start of action - change special state to true (i.e. attach "spin" till "heavy action" in process)
  2. do action in SYNC way
  3. at end of action - change same special state to false

p.s.: yes, some kind of decorator, that dispatches an action at start and before end of action.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants