有限状态机是模拟世界上大多数事物的非常有用的模型。简单来说,它具有三个特点: *状态(state)的总数是有限的。 *任何时刻,都只有一种状态。 *在一定条件下,它会从一种状态过渡到另一种状态。对于JavaScript来说,这意味着许多对象都可以写成有限状态机。例如,考虑网页上的菜单元素。鼠标悬停时,显示菜单;当鼠标移动时,菜单隐藏。如果用有限状态机来描述,这个菜单只有两种状态(显示和隐藏),鼠标会引起状态转换。代码可以写成这样:){ varself=this; self.on("hover",self.transition); },? //状态转换 transition:function(event){ switch(this.currentState){ case"hide": this.currentState='展示'; doSomething(); 休息; case"show": this.currentState='hide'; doSomething(); 休息; 默认: console.log('InvalidState!'); 休息; } } }; 可见有限状态机的写法逻辑清晰,表达力强,有利于事件的封装。一个对象拥有的状态越多,发生的事件越多,就越适合使用有限状态机。另外,JavaScript语言是一门异步操作比较多的语言。常见的解决方法是指定一个回调函数,但这会带来代码结构混乱、测试调试困难等问题。有限状态机提供了一种更好的方式:将异步操作与对象的状态变化联系起来,当异步操作结束时,相应的状态发生变化,从而触发其他操作。这比回调函数、事件监听、发布/订阅等方案更符合逻辑,也更容易降低代码的复杂度。下面介绍一个有限状态机函数库JavascriptFiniteStateMachine。这个库非常通俗易懂,可以帮助我们加深理解,功能也不弱。该库提供了一个全局对象StateMachine,使用该对象的create方法,可以生成一个有限状态机的实例。varfsm=StateMachine.create();生成时需要提供一个参数对象来描述实例的性质。比如红绿灯(trafficlights)可以这样描述:warn',from:'green',to:'yellow'}, {name:'stop',from:'yellow',to:'red'}, {name:'ready',from:'red',to:'yellow'}, {name:'go',from:'yellow',to:'green'} ] }); 初始红绿灯状态(初始)为绿色,events属性为触发状态变化的各种事件。例如,warn事件使绿色状态变为黄色状态,stop事件使黄色状态变为红色状态,等等。实例生成后,可以随时查询当前状态。*fsm.current:返回当前状态。*fsm.is(s):返回一个布尔值,表示状态s是否为当前状态。*fsm.can(e):返回一个布尔值,表示在当前状态下是否可以触发事件e。*fsm.cannot(e):返回一个布尔值,表示在当前状态下是否不能触发事件e。Javascript有限状态机允许为每个事件指定两个回调函数。以warn事件为例:*onbeforewarn:在warn事件发生之前触发。*onafterwarn(可简写为onwarn):warn事件发生后触发。同时,它还允许为每个状态指定两个回调函数,以绿色状态为例:*onleavegreen:离开绿色状态时触发。*onentergreen(可简写为ongreen):进入绿色状态时触发。假设warn事件状态由green变为yellow,以上四类回调函数的发生顺序为:onbeforewarn→onleavegreen→onenteryellow→onafterwarn。除了为每个事件和状态单独指定回调函数之外,您还可以为所有事件和状态指定一个公共回调函数。*onbeforevent:在任何事件发生之前触发。*onleavestate:离开任何状态时触发。*onenterstate:进入任何状态时触发。*onafterevent:在任何事件结束后触发。如果事件的回调函数中有异步操作(比如与服务器的Ajax通信),那么我们可能希望等到异步操作结束后,状态才会发生变化。这将使用过渡方法。fsm.onleavegreen=function(){ light.fadeOut('slow',function(){ fsm.transition(); }); returnStateMachine.ASYNC; }; 在上面代码的回调函数中,有一个异步操作(light.fadeOut)。如果不希望状态立即改变,需要让回调函数返回StateMachine.ASYNC,表示状态暂时不会改变;等到异步操作结束,再调用transition方法使状态发生变化。Javascript有限状态机还允许指定错误处理函数,这些函数在发生当前状态不可能发生的事件时自动触发。varfsm=StateMachine.create({ //... error:function(eventName,from,to,args,errorCode,errorMessage){ return'event'+eventName+':'+errorMessage; }, //... }); 比如当前状态为绿色,理论上只能发生warn事件。如果此时发生stop事件,就会触发上面的错误处理函数。Javascript有限状态机的基本用法如上。更详细的介绍请参考其主页。原文链接:http://www.ruanyifeng.com/blog/2013/09/finite-state_machine_for_javascript.html
