Javascript 有限状态机使用

大家好,我是IT修真院深圳分院第01期学员,一枚正直纯洁善良的web程序员。

今天给大家分享一下,修真院官网JS(职业)任务4,深度思考中的知识点——JavaScript 有限状态机

1. 介绍

有限状态机是一种模型,用来模拟事物。事物一般有以下特点:

1)可以用状态来描述事物,并且任一时刻,事物总是处于一种状态;

2)事物拥有的状态总数是有限的;

3)通过触发事物的某些行为,可以导致事物从一种状态过渡到另一种状态;

4)事物状态变化是有规则的,A状态可以变换到B,B可以变换到C,A却不一定能变换到C;

5)同一种行为,可以将事物从多种状态变成同种状态,但是不能从同种状态变成多种状态。

2. 涉及

2.1 回调函数callback

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

代码示例:

//异步请求回调函数

$.get('ajax/test.html',function(data){

$('.result').html(data);

});

//点击事件回调函数

$('#target').click(function(){

alert('Handle for .click() called.');

});

//数组中遍历每一项调用的回调函数

this.tabs.forEach(function(tab,index){

if(tab.selected){

this.forcustab = this.tabs[index];

}

}.bind(this));

//同步回调

function getNodes(params,callback){

var list = JSON.stringfy(params);

typeof(callback)==='function' && callback(list)

}

getNodes('[1,2,3]',function(nodes)){

//operations;

};

2.2 用对象来表现状态机模型:

有一个菜单元素,鼠标悬停时,菜单显示;鼠标移开时,菜单隐藏。

var fsm={

// 当前状态

currentState: 'hide',

// 绑定事件

initialize: function() {

var self = this;

self.on("hover", self.transition);

},

// 状态转换

transition: function(event){

switch(this.currentState) {

case "hide":

this.currentState = 'show';

doSomething();//在此调用回调函数

break;

case "show":

this.currentState = 'hide';

doSomething();//在此调用回调函数

break;

default:

console.log('Invalid State!');

break;

}

},

//callback

callback1:function(){...},

callback2:function(){...},

...};

//执行

fsm.initialize();

...

//fsm.transition();

...

2.3 Javascript Finite State Machine 函数库

javascript-state-machine插件

交通信号灯的模型描述:

var fsm = StateMachine.create({

initial: 'green',

events: [

{ name: 'warn',  from: 'green',  to: 'yellow' },

{ name: 'stop', from: 'yellow', to: 'red' },

{ name: 'ready',  from: 'red',    to: 'yellow' },

{ name: 'go', from: 'yellow', to: 'green' }

],

callbacks:{

callback1:function(){...},

callback2:function(){...},

...

},

error: function(){...}

});

initial选项用来表示fsm对象的初始状态,events选项用来描述fsm对象所有状态的变化规则,每一种变化规则对应一种行为。create方法为实例的每一种行为都添加了一个方法,调用这个方法就相当于触发对象的某种行为,当对象行为发生时,对象的状态就可以发生变化。如以上例子创建的实例将拥有如下行为方法:

fsm.warn() : 调用该方法,实例状态将从'green'变为'yellow'

fsm.stop() : 调用该方法,实例状态将从'yellow'变为'red'

fsm.ready() : 调用该方法,实例状态将从'red'变为'yellow'

fsm.go() : 调用该方法,实例状态将从'yellow'变为'green'

这些方法是StateMachine根据create时配置的events规则自动创建的,方法名跟events规则里面的name属性对应,events规则里面有几个不重复的name,就会添加几个行为方法。同时为了方便使用,它还添加了如下成员来判断和控制实例的状态和行为:

fsm.current - 返回实例当前的状态

fsm.is(state) - 如果传入的state是实例当前状态就返回true

fsm.can(eventName) - 如果传入的eventName在实例当前状态能够被触发就返回true

fsm.cannot(eventName) - 如果传入的eventName在实例当前状态不能被触发就返回true

fsm.transitions() - 以数组的形式返回实例当前状态下能够被触发的行为列表

Javascript Finite State Machine允许为每个事件指定两个回调函数,以warn事件为例:

onbeforewarn:在warn事件发生之前触发

onafterwarn(可简写成onwarn) :在warn事件发生之后触发。

同时,它也允许为每个状态指定两个回调函数,以green状态为例:

onleavegreen :在离开green状态时触发

onentergreen(可简写成ongreen) :在进入green状态时触发。

假定warn事件使得状态从green变为yellow,上面四类回调函数的发生顺序为:

onbeforewarn → onleavegreen → onenteryellow → onafterwarn。

还为所有的事件和状态指定通用的回调函数:

onbeforeevent :任一事件发生之前触发

onleavestate :离开任一状态时触发

onenterstate :进入任一状态时触发

onafterevent :任一事件结束后触发

以{ name: 'warn',  from: 'green',  to: 'yellow' }为例,这八个回调函数顺序为:

onbeforewarn

onbeforeevent

onleavegreen

onleavestate

onenteryellow

onenterstate

onafterwarn

onafterevent

2.4 开关组件实例

var Switch = function ($elem) {

var log = function (from, to) {

console.log('currentState is : ' + to + ((from || '') && (' , and previous state is : ' + from)));

},

fsm = StateMachine.create({

initial: 'off',

events: [

{name: 'turnOn', from: 'off', to: 'on'},

{name: 'turnOff', from: 'on', to: 'off'}

],

callbacks: {

onafterturnOn: function(event, from ,to){

$elem.addClass('on');

log(from, to);

},

onafterturnOff: function(event, from, to) {

$elem.removeClass('on');

log(from, to);

}

}

}

);

$elem.on('click', function(){

fsm[fsm.transitions()[0]]();

});

log(undefined, fsm.current);

return fsm;

};

在实际应用中,可能会碰到在行为触发期间,因为某些条件不允许需要取消该行为的情况,以免对象状态被错误的更改,javascript-state-machine提供了3种方式来取消行为:

在onbeforeEVENT_NAME回调中return false可以取消当前触发的行为;

在onleaveSTATE回调中return false也可以取消当前触发的行为;

在onleaveSTATE回调中return StateMachine.ASYNC来执行异步的行为。

前两种方法,在指定的回调中return false即可取消行为,第三个方法返回的仅是一个异步标识,是否取消行为需要在

异步任务的回调里面进一步指定。这个方法适用于那些带有异步任务的行为,就是说在这种行为触发的时候,并不是同时就

触发对象状态的改变,而是要等到异步任务执行完成之后再改变状态.

3. 常见问题

如何使用?

4. 解决方法

将需求模型化,划分状态和相应的触发事件与动作,利用这些构建类,控制执行。

5. 编码实战

信号灯实例

6. 扩展思考

Defered对象和Promise对象都是通过状态来控制回调

7. 参考文献

1:阮一峰:Javascript与有限状态机

2:流云诸葛:用有限状态机的思路定义组件

3:Cayley的世界:关于回调函数callback

8. 更多讨论

自行创建状态模型类

鸣谢

感谢大家观看

PPT链接

视频链接


JS有限状态机使用_腾讯视频

------------------------------------------------------------------------------------------------------------------------

今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~

下期预告:JS原型链和访问对象原型的方法,不见不散~

你可能感兴趣的:(Javascript 有限状态机使用)