Documentation
The nFlow API is designed to be simple and easy to use.
Essentially, the heart of nFlow is only 3 methods : create, on and emit.
Since in nFlow there is only one type of object, the same API applies to every object created or emitted.
Whether they are used as dispatchers, events, stores or controllers - they are the same type of objects and share the same API.
API Reference
create
flow.create([name], [...data])
Creates a new flow object.
Arguments
[name](String): the name of the new flow object.[...data](*): the data to be stored in the flow object. Can be of any type.
Returns
- the new
flowinstance
Note: The parent of the new object is automatically set to the flow object it was created from.
Example
let a = f.create('a')
let b = f.create('b')
let c = a.create('c')
let d = a.create('d')
Aliases
The following command chains are identical:
.create('a', someData).create('a').data(someData).create().name('a').data(someData)
on
flow.on(name, ...listeners)
Adds a listener to the flow object
Arguments
name(String): the name of the listener. The listener will be invoked if a flow object travelling through the current node has exactly the same name...listener(Function): The callback function to be invoked. If you specify multiple listeners, they will called in sequential order:
flow.on('registerUser', validateName
, validateEmail
, validatePassword
, register)
Returns
- setter: the new
flowinstance - getter: the currently registered listeners:
.on('foo') // returns [listener1, listener2]
.on()// returns { foo: [listener1, listener2], bar:[listener3] }`
Deleting and Augmenting Listeners:
flow.on('foo', a,b,c)
// subsequent calls on the same listener will OVERWRITE the previous listeners:
flow.on('foo', d,e) // a,b or c WILL NOT be triggered
// setting a listener to null DELETES ALL listeners:
flow.on('foo', null) // no listeres will be triggered
Example
// in services.js:
...
var services = f.create('service')
// in user-service.js:
...
services
.create('user')
.on('login' , login)
.on('logout' , logout)
.on('register', validateName
, validateEmail
, validatePassword
, register)
// in ui.js:
...
var ui = f.create('ui')
var form = ui.create('form')
...
// when the user click on the submit button:
form.emit('register', email, name, password)
emit
foo.emit([name], [...payload])
Emits an event.
The
.emitAPI has two distinct behaviours:foo.emit() // turns foo into an event and emits it foo.emit('bar') // creates bar and emits it on fooThe following 2 operations are essentially the same:
foo.emit('bar')foo.create('bar').emit()
Arguments
[name](String): the name of the new flow object to be created and emitted. If no name is given, the current flow object will be emitted....payload(*): the data to be carried in the event. Multiple parameters are accepted:
a.on('registerUser', function(name, email, password){ ... })
...
b.emit('registerUser', name, email, password)
Returns
- the emitted
flowinstance
Listener Context
Listeners are invoked in the context of the emitted event.
In the listeners the this keyword always refers to the invoking event.Since events are also flow objects, you can dispatch further events on them!
name
flow.name() // returns the name of the flow object
flow.name('foo') // sets the name of the flow object
Getter/Setter
Arguments
name(String): the name of the new flow object.
Returns
- Getter:
name(String): the name of the flow object - Setter: the
flowinstance
call
flow
.create('foo')
.call(callback) // calls callback with the foo flow object
.create('bar')
Invokes the callback function, passing in the current flow object and any optional parameters. Useful for getting an instance of the flow object in the middle of a method chain.
Arguments
callback(Function): callback function to be called with the current flow object.[...argument](*): additional parameters to be passed into callback
Returns
flow: the current flow instance
data
flow.data() // returns the data stored in the flow object
flow.data(...args) // sets some data to be stored in the flow object
Getter/Setter
Arguments
[...data](*): the data to be stored in the flow object. Can be of any type.
Returns
- Getter:
...data(*): the data stored in the flow object - Setter: the
flowinstance
Note: If multiple data objects are stores in a flow instance, the getter will return them in an array,
eg.: setting.data(foo, bar), then calling.data()will return[foo, bar]
children
flow.children() // returns an array of all child flow objects.
Returns an array of direct child nodes. To get all downstream nodes recursively, use the .get.all API
Getter only. To add a new child use f.create('new-child-name'). To add an existing child, use: child.parent(f)
Returns
[...flow]An array of all immediate child flow objects
Note: this API only returns the immediate children. If you need to access all child objects recursively, use the
.get.allAPI
Example
f.create('a')
f.create('b')
.create('d')
f.create('c')
f.children() // returns [a,b,c]
get
aliases for get:
find
flow.get(matcher, recursive)
Getter only
The get API searches all direct children and returns the first result. If the recursive parameter is set to true, indirect children are searched, too
Arguments
matcher(String or Function): the name of the flow object to find, or a mathcer function[recursive](Boolean): iffalse: only immediate child nodes are searched
Returns
- flow (flow): the first flow instance that passes the matcher test
Note:
Matcher Functions are invoked multiple times with a single parameter: the currently tested flow object. If the function returnstrue, the flow is added to the result.
Example
f.create('a', 9)
f.create('b')
f.create('c', 9)
.create('d')
f.get('a') // returns a
f.get('d') // returns null (since d is not a direct child)
f.get('d', true) // returns d
f.get(child=>child.data()==9) // returns a, the first node where data = 9
get.all
aliases for get.all:
find.all
flow.get.all(matcher, recursive)
Getter only
Same as the get API, but ALL matching nodes are returned
Arguments
matcher(String or Function): the name of the flow object to find, or a mathcer function[recursive](Boolean): iffalse: only immediate child nodes are searched
Returns
[...flow](Array): all flow instances that pass the matcher test
Example
f.create('a', 9)
f.create('b')
f.create('c', 9)
.create('d')
f.get.all('a') // returns [a]
f.get.all('d') // returns [] (since d is not a direct child)
f.get.all('d', true) // returns [d]
f.get.all(child=>child.data()==9) // returns [a,c]
parent
f.parent()
f.parent(newParent) // re-parents the node to newParent
f.parent(null) // detaches the current node
Detaches or re-parents the current node.
Getter/Setter
Arguments
newParent(flow): a flow object to reparent, ornullto detach the current node
Returns
- getter:
parent(flow): The current parent (ornullif the current node is detached) - setter:
flow(flow): the current node
Example
var a = f.create('a')
a.create('a1')
a.create('a2')
f.create('b')
a.parent(null
Note:
Setting.parent(null)will detach the branch, turning it into a new tree. No events will travel in or our between isolated trees.
parents
f.parents()
Retuns an array of all parents, starting from the elements parent, going upstream until a root node is found.
Getter only
Returns
...parents(Array): An array of flow objects
Example
var a = f.create('a')
var b = f.create('b')
var c = a.create('c')
var d = a.create('d')
var e = d.create('e')
c.parents() // returns [d,a,f]
Note:
It is possible to introduce cyclic dependency by setting one of the parents'.parentnode to a child node. In this scenario.parents()will return an array of all unique parent nodes
status
f.status()
Returns the current status of the node.
Getter only.
Returns
status(String): One of the following status indicators:flow.status.IDLE:
The default state of a flow objectflow.status.FLOWING:
The flow object has been emitted and is currently traversing the treeflow.status.STOPPED:
The flow object has been stopped during propagation.flow.status.COMPLETED:
The flow object has been delivered to all listeners.flow.status.CANCELLED:
The flow object has been cancelled.
No further events will be emitted or received on cancelled nodes or any of their child nodes
direction
f.direction()
f.direction(flow.direction.UPSTREAM)
Defines the flow direction of an emitted node. The flow direction defines how an emitted flow object traverses the tree when it gets emitted.
Getter/Setter
Returns
- if setter:
flow(flow): the current node if getter:
direction(String): One of following direction indicators:flow.direction.DEFAULT:
The default flow direction. When the node is emitted, it travels upstream until it finds the root node, then travels downstream to reach all recipients.
Downstream traversal is depth-first.flow.direction.UPSTREAM:
When the node is emitted, it travels upstream until it finds the root node, then it stops.flow.direction.DOWNSTREAM:
When the node is emitted, it travels downstream until it has reached all recipients. The downstream traversal is depth-first.flow.direction.NONE:
When the node is emitted, it only notifies listeners attached to itself and the emitter node, then it stops.flow.status.ROOT:
When the node is emitted, it flows upstrem to the root node, and only notifies listeners on that node.
Note:
If Circular Dependency is detected in the tree (ie. a parent has been reparented as a downstream child), event delivery stops as soon as all unique listeners have been notified.
cancel
flow.cancel()
Setter only.
Cancelling a flow object has the following effects: - If the object is used as an event, it will immediately stop invoking subsequent listeners - No further events can be dispatched or received on cancelled flow objects or their downstream child objects
Returns
- the current flow object
Note
Cancelling a flow object effectively cancels all of its child objects recursively.
Example
var a = f.create('a')
var b = f.create('b')
var c = a.create('c')
var d = a.create('d')
a.cancel()
isCancelled
flow.isCancelled()
Getter only.
Returns
- (Boolean) true if the current flow object or any of its parents have been cancelled.
stopPropagation
flow.stopPropagation()
Setter only.
Invoking .stopPropagation() will stop delivering the event to further listeners.
Returns
- the current flow object
Difference between
stopPropagationandcancellation:Cancelling an event has a lasting effect: no further events can be dispatches or received on a cancelled flow object or its children(recursively).
In contrast -
stopPropagationsimply stops the current event delivery - but the flow object stays active - you can still send or receive events on them.
propagationStopped
flow.propagationStopped()
``
Getter` only.
Returns
- (Boolean) true if
.stopPropagation()has been called on the current flow object
guid
flow.guid() //returns 1234
Getter only.
Returns
- the unique identifier of the flow object.
toString
flow.toString()
Getter only.
Returns
- a stringified representation of the current flow object. Useful for logging.
toObj
flow.toObj()
Getter only.
Returns
- a static object representation of the current flow object:
{
name: 'foo',
guid: 1234,
status: 'IDLE'
listeners:['hello']
children:[
name: 'bar',
guid: 2345
]
parent:{
name: 'a'
guid: 5432
}
}