Created
November 22, 2014 11:44
-
-
Save IUnknown68/182662c6d5bda213b32c to your computer and use it in GitHub Desktop.
InitManager is a simple state machine, that runs an `init` or `shutdown` function for each state. It has methods to walk up or down to a certain state, and makes sure that each `init` (for walking up) or `shutdown` (waliking down) is called exactly once and only if needed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//============================================================================== | |
// class InitManager | |
function InitManager(arStates) { | |
var _state = 0; | |
//---------------------------------------------------------------------------- | |
// privates | |
// return `aState` limited to a valid arStates index | |
var _sanitizeState = function(aState) { | |
return Math.min(Math.max(parseInt(aState)||0, 0), arStates.length-1); | |
} | |
// sort arguments | |
// return a valid newState and args | |
var _getArgs = function(newState, args, defaultState) { | |
defaultState = _sanitizeState(defaultState); | |
var t = typeof newState; | |
var ret = {newState: newState, args: args}; | |
if ('undefined' === t) { | |
// not set - set default | |
ret.newState = defaultState; | |
} | |
else if ('object' === t) { | |
// newState is args - set default... | |
ret.newState = defaultState; | |
// ...and set args | |
ret.args = newState; | |
} | |
else { | |
// newState supposed to be a state | |
ret.newState = _sanitizeState(newState); | |
} | |
return ret; | |
} | |
// run a certain state: init or shutdown | |
var _runState = function(aFnName, aState, aArgs) { | |
var args = ( ('undefined' !== typeof aArgs) && ('undefined' !== typeof aArgs[aState]) ) ? | |
aArgs[aState] : | |
undefined; | |
var state = arStates[aState]; | |
if ('function' === typeof state[aFnName]) { | |
state[aFnName].apply(state, args); | |
} | |
}; | |
//---------------------------------------------------------------------------- | |
// public | |
// StepUp: Run `init` up to `newState` (including). | |
this.StepUp = function(newState, initArgs) { | |
var args = _getArgs(newState, initArgs, arStates.length-1); | |
for (_state; args.newState > _state; _state++) { | |
_runState('init', _state + 1, args.args); | |
} | |
}; | |
// StepDown: Run `shutdown` down to `newState` (excluding). | |
this.StepDown = function(newState, shutdownArgs) { | |
var args = _getArgs(newState, shutdownArgs, 0); | |
for (_state; args.newState < _state; _state--) { | |
_runState('shutdown', _state, args.args); | |
} | |
}; | |
} | |
//------------------------------------------------------------------------------ | |
// SAMPLE | |
//------------------------------------------------------------------------------ | |
//------------------------------------------------------------------------------ | |
// class implementing `init` and `shutdown` methods | |
function InitState(name) { | |
this.name = name; | |
} | |
InitState.prototype = { | |
init: function() { | |
console.log('init: %s. Args: ', this.name, arguments); | |
}, | |
shutdown: function() { | |
console.log('shutdown: %s', this.name); | |
} | |
}; | |
// Instance of `InitManager` | |
// Constructor takes an array of objects, each having an `init` and a `shutdown` | |
// method. | |
var manager = new InitManager([ | |
new InitState('None:0'), | |
new InitState('Base:1'), | |
new InitState('App:2'), | |
new InitState('Background:3'), | |
new InitState('Controls:4'), | |
new InitState('Events:5') | |
]); | |
// enum for readable states | |
var None = 0, | |
Base = 1, | |
App = 2, | |
Background = 3, | |
Controls = 4, | |
Events = 5; | |
// Arguments for init calls. | |
// Can be an array or an object - the numeric state is the | |
// key in any case. | |
// Each entry contains the arguments to pass to the `init` | |
// call of the state. | |
// Each entry has to be an array. | |
var initArgs = { | |
}; | |
// some sample args | |
initArgs[Base] = ['foo', 'bar']; | |
initArgs[Controls] = [{width: 100, height: 300}]; | |
// Additionally there can also be shutdown arguments - not shown here. | |
//------------------------------------------------------------------------------ | |
// MAIN | |
console.log('-------- StepUp(Background)'); | |
manager.StepUp(Background, initArgs); | |
console.log('----------------------------------------'); | |
console.log('.'); | |
console.log('-------- StepDown(Base)'); | |
manager.StepDown(Base); | |
console.log('----------------------------------------'); | |
console.log('.'); | |
console.log('-------- StepUp()'); | |
manager.StepUp(initArgs); | |
console.log('----------------------------------------'); | |
console.log('.'); | |
console.log('-------- StepDown()'); | |
manager.StepDown(); | |
console.log('----------------------------------------'); | |
console.log('.'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can run a bunch of
init
/shutdown
functions in a certain order. Has methods for spinning up / down to a certain state and call theinit
method when spinning up, and theshutdown
method on spinning down.