@wildpeaks/actions-worker
TypeScript icon, indicating that this package has built-in type declarations

2.2.0 • Public • Published

ActionsWorker

Build Status

Typescript class to store an immutable state that can be edited using actions, and emits JSON props on state change.

The EntryLoader uses it to generate a Web Worker automatically as part of the JSON Entries system for Webpack, but this package can also be used on its own, even without a Web Worker.

Install:

npm install @wildpeaks/actions-worker

Example:

import {ActionsWorker, IDispatcher} from '@wildpeaks/actions-worker';


// The immutable state could be a simple frozen object, class instance, etc.
// It's up to you.
type State = {
	readonly count: number;
};


// Props must be a JSON-compatible frozen object.
// This way, it could be forwarded from a Web Worker to the main thread
// for rendering with React or Preact, for example.
// Technically it doesn't have to be frozen, but it is assumed to be immutable.
type Props = {
	readonly text: string;
};


// String values are easier to debug.
enum Actions {
	ADD = 'add',
	SUBTRACT = 'subtract'
}

// But you can use a classic integer enum as well.
// enum Actions {
// 	ADD,
// 	SUBTRACT
// }


// Each action has a matching data message.
// The only requirement is property `action`.
type AddMessage = {
	action: Actions.ADD;
	delta: number;
};
type SubtractMessage = {
	action: Actions.SUBTRACT;
	delta: number;
};
type Messages = AddMessage | SubtractMessage;
type Dispatcher = IDispatcher<State, Messages>;


// Actions are simple functions with two arguments:
// - the data message
// - a reference to read/write the new state & scheduled additional actions.
//
// Note that package `@wildpeaks/frozen` makes it simpler to manipulate
// frozen objects, if the following is too verbose.
function add(message: AddMessage, dispatcher: Dispatcher): void {
	const oldState: State = dispatcher.state;
	const newState: State = {
		count: oldState.count + message.delta
	};
	dispatcher.state = Object.freeze(newState);

	// Actions are only allowed ONE immediate change to the state.
	// It must schedule any delayed or additional changes using `dispatcher.schedule`.
}

function subtract(message: SubtractMessage, dispatcher: Dispatcher): void {
	const oldState: State = dispatcher.state;
	const newState: State = {
		count: oldState.count - message.delta
	};
	dispatcher.state = Object.freeze(newState);
}


// Subclass the ActionsWorker class to specify the list of actions
// and the way to extract render Props from State (using `serialize`).
class Storage extends ActionsWorker<Props, State, Messages> {
	constructor() {
		super();
		this.actions[Actions.ADD] = add;
		this.actions[Actions.SUBTRACT] = subtract;
	}
	protected serialize(state: State): Props {
		const props: Props = {
			text: `Count is ${state.count}`
		};
		Object.freeze(props);
		return props;
	}
}


const store = new Storage();

// Receives the results of serialize(state),
// ready to be rendered by React or Preact for example.
store.onprops = props => {
	console.log(props);
};

// Initial state
store.state = {
	count: 0
};

// Trigger actions by pushing to the queue.
// The dispatcher that actions receive also has the `schedule` method.
// Messages are JSON-compatible, so the storage could be in a WebWorker
// while the messages are sent from the main thread.
// They could also be recorded for playback.
store.schedule({
	action: Actions.ADD,
	delta: 1
});
store.schedule({
	action: Actions.ADD,
	delta: 10
});
store.schedule({
	action: Actions.SUBTRACT,
	delta: 200
});

Package Sidebar

Install

npm i @wildpeaks/actions-worker

Weekly Downloads

1

Version

2.2.0

License

MIT

Unpacked Size

8.19 kB

Total Files

4

Last publish

Collaborators

  • cecilemuller