stackfire v3.0.0-alpha.12b
Stackfire
Route driven async control flow library (and pattern) for your next game or app
Install
npm install stackfire --save
Usage
const stack = require('stackfire')
stack.on('moon-shot', () =>
console.log('we about to shoot for the moon!')
) //^this listener is synchronous
stack.on('moon-shot', (next) => {
console.log('launch!!')
launchCraft()
setTimeout(next, 1000)
})
//^this listener is asynchronous
//(note the use of next)
stack.on('moon-shot', () => showText('craft launched!'))
//^this listener will execute last
//(even though it is synchronous)
stack.fire('moon-shot')
API
stack.fire
stack.fire(command, callback)
Fire command
; invokes all listeners for said command in sequence, followed by an optional concluding callback
stack.fire('green')
stack.fire('red', () => console.log('runs last'))
stack.on
stack.on(command, callback)
Creates a listener that invokes callback
on the given command
stack.on('green', () => console.log('its green'))
stack.on(next)
stack.on((next) => callback)
Pass an optional next
object to stack.on
to make your listener asynchronous; the entire stack will hold while said listener executes until the next
object itself is invoked.
stack.on('go', (next) => {
setTimeout(() => {
console.log('go!')//< executes first
next()
}, 100)
})
stack.on('go', () => console.log('going!'))
//^ executes last (after 100ms) despite being synchronous function
stack.fire('go')
next.fire
The next object can be optionally used to invoke a nested command.
stack.on('detonate-apple', (next) => {
next.fire('detonate-bannana')
})
stack.on('detonate-apple', () => {
setTimeout(() => {
detonate('apple') //< executes last
}, 100)
})
stack.on('detonate-bannana', (next) => {
setTimeout(() => {
detonate('bannana')//< executes first
next()
}, 100)
})
stack.fire('detonate-apple')
//(completes in 200ms)
If next.fire is called within a listener, as shown on line 2 above, it will invoke the stated command as a child of the command in progress - branching from the current stack of listeners from where it was called - to a new column over - returning upon completion of said child command back to the original column where it left off to finish remaining listeners not yet run.
stack.params
property
Parameters as part of the current command in progress (ie: do-something/:time
) are available as a property of the stack.params
object (ie: stack.params.time
).
If an object is supplied as parameter in a stack.fire
that object will be available to all listeners down the chain via stack.params.body
Ex:
stack.on('green', () => console.log(stack.params.body.fruit)) //> "apple"
stack.fire('green', { fruit : "apple" })
Experimental features
The following features are not well tested or supported yet:
stack.aliaser
Create an aliaser to enable shorthand aliases:
const fire = new stack.aliaser()
stack.on('fruit/apple', () => console.log('good in shakes'))
fire.fruitApple()
// > 'good in shakes'
stack.buffer
Creates a listener ala stack.on
but instead of running one time it will run before and after every other listener established in the stack.
stack.on('snow', () => console.log("shovel sidewalk"))
stack.buffer('snow', () => console.log("it's snowing"))
stack.fire('snow')
// > it's snowing
// > shovel sidewalk
// > it's snowing
stack.first
Same as stack.on
but your listener will run first
stack.second
Same as stack.on
but your listener will run second. stack.third
, stack.fourth
etc also work or use stack.nth(priority)
where priority
is an integer indicating at what place the listener should run.
stack.last
Same as stack.on
but your listener will last
stack.endCommand
Invoke this function from within a listener to rematurely end a command, prevents any further listeners down the stack from running on this call.
stack.endParent
Same as stack.endCommand
but ends the parent command of the current command (of the listener from which you invoke this function) in progress.
stack.utils
Synchronously executed array of functions that will run at various points of stack's execution.
stack.libs
Array of async libraries you can feed stack for the purpose of wrapping functions to 'stackify' them ie- to fire them in your stack.
const Pouchdb = require('pouchdb')
const db = new PouchDB('example')
stack.libs.push(db)
let data = { _id: 'cashews', awesome : true }
stack.on(db.post, () => {
console.log('about to post to db...')
stack.params.body.awesome = false
})
stack.fire(db.post, data, () => {
console.log('posted data to db!')
console.log(stack.err)
//> null
console.log(stack.res)
//> { _id: 'cashews', _rev : '1-967a00dff5e', awesome : false }
})
Testing
Git clone the repo and run npm install; npm test
To run only a specific test edit test.js with newTest.only
(instead of newTest
) or from command line without needing to modify the script you can run:
node run-test.js "No doubling up of one time listener/trailing callbacks" | ./node_modules/.bin/tap-spec
TODO
- finish documenting features
- improve performance
- fix bugs / add more test cases and more thorough testing of different configurations
- Tools/Visualizer and extra utility modules
License
MIT
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago