event-flow
v0.0.8
Published
Event Flow: Functional JavaScript event plumbing
Downloads
5
Readme
Event Flow
npm install --save event-flow
Functional JavaScript event plumbing
Event Flow is a declarative syntax for expressing how data moves through functions.
Quick overview
- Define an event as a function that 1) is called with other functions, and 2) calls those other functions in the future. Let's call those other functions "delegates". This model is consistent with how Redux's
store.subscribe
function behaves. - Delegates come in two flavors. 1) One is defined by
.call( ... )
which simply calls the given function, and 2) the other is defined by.pipe( ... ).to( ... )
, which calls thepipe
function with theto
function. The advantage of approach #2 is that you can generalize how data flows to theto
function. Thepipe
may choose to call it once, never, many times, after a Promise is resolved, etc... depending on the event arguments. And, the logic of how data flows to theto
function is decoupled from the function itself. For example, you could callto
with Reduxstore.dispatch
if you're piping actions.
API
createEvent(event)
event
is a function of a function, e.g. Reduxstore.subscribe
.- Returns a new instance of the
EventFlow
class. - (Note: All methods of
EventFlow
are composable, meaning that they all returnthis
.)
EventFlow.pass(source)
source
is a function called at event time. Its return value is passed as an argument to each event delegate. Ifpass
is called multiple times, then multiple arguments will be passed in the order of the calls.- Returns
this
.
EventFlow.call(delegate)
delegate
is a function called at event time with arguments.- Returns
this
.
EventFlow.pipe(delegate)
delegate
is a function called at event time with a "yield" function, plus arguments.delegate
may asynchronously call the "yield" function, which is defined by the next call toEventFlow.to
.- Returns
this
.
EventFlow.to(yield_function)
- Defines the yield function passed to a
pipe
delegate, which is defined by the previous call toEventFlow.pipe
. - Returns
this
.
Simple example with Redux
import { createEvent } from 'event-flow';
import { createStore } from 'redux';
const store = createStore((state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'RESET':
return 0;
default:
return state;
}
});
const actions = (push, state) => {
if (state === 10) {
push({ type: 'RESET' });
setTimeout(() => push({ type: 'RESET' }), 500);
}
};
// Create a simple event flow that dispatches actions after a change to state (and logs the state).
createEvent(store.subscribe)
.pass(store.getState)
.call(state => console.log(`state = ${state}`))
.pipe(actions).to(store.dispatch);
// Dispatch INCREMENT actions every 100ms.
setInterval(() => store.dispatch({ type: 'INCREMENT' }), 100);
Console output:
state = 1
state = 2
state = 3
state = 4
state = 5
state = 6
state = 7
state = 8
state = 9
state = 10
state = 0
state = 1
state = 2
state = 3
state = 4
state = 0
state = 1
state = 2
state = 3
state = 4
state = 5
state = 6
state = 7
state = 8
state = 9
state = 10
state = 0
state = 1
state = 2
state = 3
state = 4
state = 0
state = 1
state = 2
state = 3
state = 4
state = 5
state = 6
state = 7
state = 8
state = 9
state = 10
state = 0
etc...