Introducing: Spasm
∞ published on at with comments and reactions
Spasm is a super-primitive asynchronous state machine for Node.js. While working on another yet-to-be-announced open-source project, I was looking for a way to manage logic for a CLI. For whatever reason, I thought using a state machine might be an interesting approach. I created the module in a single Seattle-to-Kent train commute and spent the following commute packing it up as a proper npm module. It’s a whopping 37 lines of code (plus 214 for tests).
Installation
$ npm install spasm
Usage
Spasm is extremely simple to use. Here’s an example using Commander.js to prompt the user for input from the command line until a non-empty string is provided:
var spasm = require('spasm');
var program = require('commander');
var machine = spasm({
'prompt': function(next, context) {
program.prompt('What’s your name? ', function(name) {
if ('' === name) {
next('prompt');
} else {
context.name = name;
next('display');
}
});
},
'display': function(next, context) {
console.log(context.salutation, context.name);
process.exit(0);
}
});
machine('prompt', {
salutation: 'Hello, %s.'
});
spasm()
can be passed any object as a set of states, but it must have at least one state (a property with a function for a value). Each state will be passed a next
function and the context
of the state machine when it’s invoked. next
uses process.nextTick()
to ensure that each state is invoked asynchronously. The default context is an empty object ({}
) if one isn’t passed when the machine is started. If a state makes any changes to context
, it will automatically be reflected in any subsequent states. Alternatively, you can pass an entirely new context to next()
as a second argument.
I didn’t bother putting any effort into ensuring that the state machine can’t be forked to multiple concurrent states, but maybe that’s a feature — not a bug.
Give it a spin and let me know what you think.