anthonyv
anthonyv

Reputation: 2465

Redux connect chaining async actions

I am in the process of trying to setup redux, react-redux and redux-thunk. Thinks are generally going well but I have a question about how things are supposed to look when chaining multiple async actions together.

Specifically I have a scenario where the actions can be invoked individually or indirectly by another action which can invoke them. My question is how should selectItem be authored if I want to be idiomatic?

action.js

export function fetchByContext(contextId) { 
    return dispatch => {
        _fetchByContext(messages => { 
            dispatch({ type: RECEIVE_MESSAGES, ... });
        });
    };
};

export function subscribeByContext(contextId) {
    return dispatch => {
        _subscribeByContext(messages => { 
            dispatch({ type: RECEIVE_MESSAGES, ... });
        });
    };
};

export function selectItem(contextId) {
    return dispatch => {
        subscribeByContext(contextId)(dispatch);
        fetchByContext(contextId)(dispatch);
    };
};

Upvotes: 1

Views: 1994

Answers (1)

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40296

I believe the key is that (ref):

Any return value from the inner function will be available as the return value of dispatch itself

If the inner functions of fetchByContext(), subscribeByContext() return a promise, these could be chained in series or run in parallel from selectItem(). An untested implementation, assuming neither _fetchByContext() nor _subscribeByContext() return a promise would be:

export function fetchByContext(contextId) { 
    return dispatch => {
        return new Promise((resolve, reject) => {
            _fetchByContext(messages => { 
                dispatch({ type: RECEIVE_MESSAGES, ... });
                resolve(messages);
            });
        });
    };
};

export function subscribeByContext(contextId) {
    return dispatch => {
        return new Promise((resolve, reject) => {
            _subscribeByContext(messages => { 
                dispatch({ type: RECEIVE_MESSAGES, ... });
                resolve(messages);
            });
        });
    };
};

export function selectItem(contextId) {
    return dispatch => {
        // CALL IN SERIES
        return dispatch(subscribeByContext(contextId))
            .then(() => dispatch(fetchByContext(contextId)));
        // CALL IN PARALLEL (alternative to the code above; this is probably not what you want - just keeping for reference)
        return Promise.all(
            dispatch(subscribeByContext(contextId)),
            dispatch(fetchByContext(contextId))
        );
    };
}

Again please note the code above is untested, just in hope of giving an idea for the general solution.

Upvotes: 1

Related Questions