Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.

License

NotificationsYou must be signed in to change notification settings

fschaefer/Stately.js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stately.js Logo

What is it?

Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.jsand the browser.

Installation

In Node.js you can install Stately.js withnpm:

$ npm install stately.js

and include it to your project by:

varStately=require('stately.js');

Alternately, you can install Stately.js withbower:

$ bower install --save Stately.js

In browsers you can include it directly by adding it to the document head section:

<scripttype="text/javascript"src="https://raw.github.com/fschaefer/Stately.js/master/Stately.js"></script><scripttype="text/javascript">// use Stately</script>

or with Asynchronous Module Definition by e.g.:

<scripttype="text/javascript"src="https://raw.github.com/jrburke/requirejs/master/require.js"></script><scripttype="text/javascript">require(['https://raw.github.com/fschaefer/Stately.js/master/Stately.js'],function(Stately){// use Stately});</script>

Usage

Creating a new machine

A new state machine can be created with either the new operator:

varmachine=newStately(statesObject,initialStateName);

or the factory method:

varmachine=Stately.machine(statesObject,initialStateName);

Both will return a newstateMachine object, with all events from all statesattached to it. The machine will transition into the initial stateinitialStateNameor the first attachedstateObject ifinitialStateName is omitted. In additionto the events thestateMachine object has agetMachineState() method, returningthe current name of the machines state,getMachineEvents(), returning possibleevents in the current state.

ThestatesObject is an object withstateObject objects attached asproperties.The property names of thestatesObject are thestates of the machine.The attachedstateObject objects model the machines states with the propertynames asevents and the connected functions asactions:

varmachine=Stately.machine({'STATE0':{event:function(){            ...}},'STATE1':{event:function(){            ...}},'STATE2':{event:function(){            ...},anotherEvent:function(){            ...}}});

If different states use the same event identifier, theevents are chained upand the machine handles calling the correctaction for the current state (iftheevent is handled in the current state). If the event is not handled inthe current state, it is ignored.

If no immediateaction needs to be declared, the desired transitionstatecan be attached to theevent as string directly:

varmachine=Stately.machine({'STATE0':{'event':/* => */'STATE1'},'STATE1':{'event':/* => */'STATE2'},'STATE2':{'event':/* => */'STATE0','anotherEvent':/* => */'STATE1'}});

Transitions

There are several ways anaction can transition the machine into anotherstate. The simplest form is returning the desired next state from an action.Therefore,this refers to the (internal)stateStore inside anaction toaccess the other states of the machine:

...'STATE1':{    doSomething:function(){        ...//transition from STATE1 to STATE2returnthis.STATE2;// as an alternative just return the new state as string// return 'STATE2';}}...

If an action should not transition the machine into another state, just omitthe return value (or return the current state).

Sometimes it is desired to return a value from an action. In this case thereturn value must be an array with two elements. The first element is the nextstate the machine should transition into, and the second element the returnvalue:

...'STATE1':{    doSomething:function(){        ...//transition from STATE1 to STATE2 and return a stringreturn[this.STATE2,'this is a return value'];}}...

For asynchronous actions there aregetMachineState() andsetMachineState(nextState) accessible through thethis reference of anaction:

...'STATE1':{    doSomething:function(){varself=this;setTimeout(function(){            ...self.setMachineState(self.STATE2);},5000);        ...}}...

Becausethis refers to thestateStore, it is also possible to call anaction from another state (note: this won't trigger thenotifications):

...'STATE1':{    doSomething:function(){        ...this.STATE2.doSomethingDifferent.call(this);        ...returnthis.STATE3.doSomethingCompletelyDifferent.call(this);}}...

Special event hook functions

Once in a while, it is useful to get anotification when the machinetransitions into another state. Therefore there are some special event namesreserved for event functions, namelyonEnter,onLeave (triggeredwhen entering / leaving a state),onBefore<eventname> andonAfter<eventname>(triggered before or after calling an event).

The event function has the following signature:

function(event,oldState,newState){    ...}

event - The event that triggered the transition.oldState - The old state the machine is transitioned from.newState - The new state the machine is transitioned into.

Inside these functions,this refers to the internalstateStore.

Examples

Door

vardoor=Stately.machine({'OPEN':{'close':/* => */'CLOSED'},'CLOSED':{'open':/* => */'OPEN','lock':/* => */'LOCKED'},'LOCKED':{'unlock':/* => */'CLOSED','break':/* => */'BROKEN'},'BROKEN':{'fix':function(){this.fixed=(this.fixed===undefined ?1 :++this.fixed);returnthis.fixed<3 ?this.OPEN :this.BROKEN;}}});//the initial state of the door is open (it's the first state object)console.log(door.getMachineState()==='OPEN');// true;//close and lock the doordoor.close().lock();console.log(door.getMachineState()==='LOCKED');// true;//try to open itdoor.open();console.log(door.getMachineState()==='OPEN');// false;//unlock, open, lock (is ignored because it fails), close, and lockdoor.unlock().open().lock().close().lock();console.log(door.getMachineState()==='LOCKED');// true;//the door is still locked, break itdoor.break();console.log(door.getMachineState()==='BROKEN');// true;//fix opens the door, close it, lock it, break it againdoor.fix().close().lock().break();console.log(door.getMachineState()==='BROKEN');// true;//and again fix opens the door, close it, lock it, break itdoor.fix().close().lock().break();console.log(door.getMachineState()==='BROKEN');// true;//fixing is limited, the door stays brokendoor.fix();console.log(door.getMachineState()==='OPEN');// false;console.log(door.getMachineState()==='BROKEN');// true;

Radio

functionreporter(event,oldState,newState){vartransition=oldState+' => '+newState;switch(transition){/*        ...        case 'STOPPED => PLAYING':        case 'PLAYING => PAUSED':        ...        */default:console.log(transition);break;}}varradio=Stately.machine({'STOPPED':{onEnter:reporter,play:function(){returnthis.PLAYING;}},'PLAYING':{onEnter:reporter,stop:function(){returnthis.STOPPED;},pause:function(){returnthis.PAUSED;}},'PAUSED':{onEnter:reporter,play:function(){returnthis.PLAYING;},stop:function(){returnthis.STOPPED;}}});radio.play().pause().play().pause().stop();//STOPPED => PLAYING//PLAYING => PAUSED//PAUSED => PLAYING//PLAYING => PAUSED//PAUSED => STOPPED

jsFiddles

About

Stately.js is a JavaScript based finite-state machine (FSM) engine for Node.js and the browser.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors4

  •  
  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp