Skip to content

Commit

Permalink
tweaks to store. support batched actions dispatching
Browse files Browse the repository at this point in the history
  • Loading branch information
sccolbert committed Jun 27, 2017
1 parent 7555db4 commit 9a529da
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 13 deletions.
4 changes: 4 additions & 0 deletions packages/datastore/src/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ interface IAction {
*
* #### Notes
* Custom actions may derive from this class.
*
* This class is useful for creating strongly-type actions which
* are combined into a discriminated union, and used from within
* a `switch` statement inside a reducer.
*/
export
class Action<T extends string> implements IAction {
Expand Down
63 changes: 51 additions & 12 deletions packages/datastore/src/datastore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,18 @@ import {
* #### Notes
* The `S` type parameter is an interface defining the state shape.
*
* The `A` type parameter is a union type of all actions supported
* by the instance of the data store.
*
* More information on redux can be found at: http://redux.js.org
*/
export
class DataStore<S, A extends IAction> {
class DataStore<S> {
/**
* Construct a new data store.
*
* @param reducer - The root reducer function for the data store.
*
* @param state - The initial state for the data store.
*/
constructor(reducer: Reducer<S, A>, state: S) {
constructor(reducer: Reducer<S>, state: S) {
this._reducer = reducer;
this._state = state;
}
Expand All @@ -65,9 +62,14 @@ class DataStore<S, A extends IAction> {
/**
* Dispatch an action to the data store.
*
* @param action - The action to dispatch to the store.
* @param action - The action(s) to dispatch to the store.
*
* #### Notes
* An array of actions will be dispatched atomically.
*
* The `changed` signal is emitted only once per dispatch.
*/
dispatch(action: A): void {
dispatch(action: IAction | IAction[]): void {
// Disallow recursive dispatch.
if (this._dispatching) {
throw new Error('Recursive dispatch detected.');
Expand All @@ -76,22 +78,59 @@ class DataStore<S, A extends IAction> {
// Set the dispatch guard.
this._dispatching = true;

// Look up the root reducer.
let reducer = this._reducer;
// Set up the new state variable.
let state: S;

// Invoke the reducer.
// Invoke the reducer and compute the new state.
try {
this._state = reducer(this._state, action);
if (Array.isArray(action)) {
state = Private.reduceMany(this._reducer, this._state, action);
} else {
state = Private.reduceSingle(this._reducer, this._state, action);
}
} finally {
this._dispatching = false;
}

// Bail early if there is no state change.
if (this._state === state) {
return;
}

// Update the internal state.
this._state = state;

// Emit the `changed` signal.
this._changed.emit(undefined);
}

private _state: S;
private _reducer: Reducer<S>;
private _dispatching = false;
private _reducer: Reducer<S, A>;
private _changed = new Signal<this, void>(this);
}


/**
* The namespace for the module implementation details.
*/
namespace Private {
/**
* Reduce a single action and return the new state.
*/
export
function reduceSingle<S>(reducer: Reducer<S>, state: S, action: IAction): S {
return reducer(state, action);
}

/**
* Reduce an array of actions and return the final state.
*/
export
function reduceMany<S>(reducer: Reducer<S>, state: S, actions: IAction[]): S {
for (let i = 0, n = actions.length; i < n; ++i) {
state = reducer(state, actions[i]);
}
return state;
}
}
2 changes: 1 addition & 1 deletion packages/datastore/src/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ import {
* A reducer processes actions to update the data store state.
*/
export
type Reducer<S, A extends IAction> = (state: S, action: A) => S;
type Reducer<S> = (state: S, action: IAction) => S;

0 comments on commit 9a529da

Please sign in to comment.