Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

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

🚦- Small Finite State Machines

License

NotificationsYou must be signed in to change notification settings

choojs/nanostate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npm versionbuild statusdownloadsjs-standard-style

Small Finite State Machines. Great data structure to make code more readable,maintainable and easier to debug.

Usage

varnanostate=require('nanostate')varmachine=nanostate('green',{green:{timer:'yellow'},yellow:{timer:'red'},red:{timer:'green'}})machine.emit('timer')console.log(machine.state)// => 'yellow'machine.emit('timer')console.log(machine.state)// => 'red'machine.emit('timer')console.log(machine.state)// => 'green'

Hierarchical

Let's implement a traffic light that flashes red whenever there's a poweroutage. Instead of adding apowerOutage event to each normal state, weintroduce a hierarchy which allows any normal state to emit thepowerOutageevent to change the state toflashingRed.

varnanostate=require('nanostate')varmachine=nanostate('green',{green:{timer:'yellow'},yellow:{timer:'red'},red:{timer:'green'}})machine.event('powerOutage',nanostate('flashingRed',{flashingRed:{powerRestored:'green'}}))machine.emit('timer')console.log(machine.state)// => 'yellow'machine.emit('powerOutage')console.log(machine.state)// => 'flashingRed'machine.emit('powerRestored')console.log(machine.state)// => 'green'

History (to be implemented)

Implementers note: keep track of the last state a machine was in before exitingto the next machine. That way if'$history' is called, it can be merged intothe previous machine.

TODO: figure out how it works if machines are combined in a non-linear fashion.

varnanostate=require('nanostate')varmachine=nanostate('cash',{cash:{check:'check'},check:{cash:'cash'}})machine.join('next',nanostate('review',{review:{previous:'$history'}}))

Parallel

Sometimes there's multiple parallel states that needexpressing;nanostate.parallel helps with that. For example when editingtext, a particular piece of text might bebold,italic andunderlined atthe same time. The trick is that all of these states operate in parallel

varnanostate=require('nanostate')varmachine=nanostate.parallel({bold:nanostate('off',{on:{'toggle':'off'},off:{'toggle':'on'},}),underline:nanostate('off',{on:{'toggle':'off'},off:{'toggle':'on'},}),italics:nanostate('off',{on:{'toggle':'off'},off:{'toggle':'on'},}),list:nanostate('none',{none:{bullets:'bullets',numbers:'numbers'},bullets:{none:'none',numbers:'numbers'},numbers:{bullets:'bullets',none:'none'}})})machine.emit('bold:toggle')console.log(machine.state)// => {//   bold: 'on',//   italics: 'off',//   underline: 'off',//   list: 'none'// }

Nanocomponent

Usage in combination withnanocomponent to create stateful UIcomponents.

varNanocomponent=require('nanocomponent')varnanostate=require('nanostate')module.exports=classComponentextendsNanocomponent{constructor(name,state,emit){super(name,state,emit)this.state={data:{},input:''}this.machine=nanostate('idle',{idle:{click:'loading'},loading:{resolve:'data',reject:'error'},data:{click:'loading'},error:{click:'loading'}})this.machine.on('loading',()=>this.searchRepositories())}createElement(){varbuttonText={idle:'Fetch Github',loading:'Loading…',error:'Github fail. Retry?',data:'Fetch Again?'}[this.machine.state]returnhtml`<div><inputtype="text"value=${this.state.input}onChange=${e=>(this.state.input=e.target.value)&&this.rerender()}><buttononClick=${()=>this.machine.emit('click')}disabled=${this.machine.state==='loading'}>${buttonText}</button>${data&&html`<div>${JSON.stringify(data,null,2)}</div>`}${this.machine.state==='error'&&html`<h1>Error</h1>`}</div>    `}searchRepositories(){fetch(`${ROOT_URL}/${this.state.input}`).then(res=>res.json()).then(res=>{this.state.data=res.datathis.machine.emit('resolve')}).catch(err=>this.machine.emit('reject'))}}

API

machine = nanostate(initialState, transitions)

Create a new instance of Nanostate. Takes the name of the initial state, and amapping of states and their corresponding transitions. A state mapping isdefined as{ 1: { 2: 3 }}, where1 is the state's name,2 is an eventname it accepts, and3 is the new state after the event has been emitted.

machine.emit(event)

Move from the current state to a new state. Will throw if an invalid command ispassed.

machine.on(state, cb)

Trigger a callback when a certain state is entered. Useful to trigger sideeffects upon state change.

state = machine.state

Return the current state.

machine.event(eventName, machine) (to be implemented)

Add another machine to the transition graph. The first argument is an eventname, which can be transitioned to from all other states in the graph.

machine = nanostate.parallel(machines) (to be implemented)

Combine several state machines into a single machine. Takes an object of statemachines, where the key is used to prefix the events for the state machine.

Say we have two state machine:'foo' and'bar'.'foo' has an event called'beep'. When combined through.parallel(), the event on the combinedmachine would be'foo:beep'.

Installation

$ npm install nanostate

See Also

License

Apache-2.0


[8]ページ先頭

©2009-2025 Movatter.jp