「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
学习有限状态机之前我们要先了解,什么是有限状态机。
有限状态机是一个非常有用的模型,可以模拟世界上大部分事物的一个数学模型。在任何时候都处于有限数量的状态之一。响应某些外部输入,就可以从一个状态转换到另一个状态。
有限状态机有三个特征:
- 状态总数(state)是有限的。
- 任意时刻,只处在一个状态之中。
- 某种条件下,会中一个状态转变到另一个状态。
而在JS中,新建一个对象,用这个对象的属性来模拟元素的状态,用这个对象的方法模拟元素在不同状态的转变。那么这个对象就是一个有限状态机。是否能用状态机描述,取决于当前状态确定,有限个状态,响应事件,在不同状态间有规律的转变。Promise就是一个有限状态机。
有限状态机需要满足所需状态确定,有事件触发转变状态,总状态有限且转变有规律。例如开关,下拉菜单,游戏中生死状态等。
今天我们通过一个开源项目来学习状态机。
javascript-state-machine
有限状态机库。
In a browser:
<script src='state-machine.js'></script>
after downloading the source or the minified version
Using npm:
npm install --save-dev javascript-state-machine
In Node.js:
var StateMachine = require('javascript-state-machine');
A state machine can be constructed using:
var fsm = new StateMachine({
init: 'solid',
transitions: [
{ name: 'melt', from: 'solid', to: 'liquid' },
{ name: 'freeze', from: 'liquid', to: 'solid' },
{ name: 'vaporize', from: 'liquid', to: 'gas' },
{ name: 'condense', from: 'gas', to: 'liquid' }
],
methods: {
onMelt: function() { console.log('I melted') },
onFreeze: function() { console.log('I froze') },
onVaporize: function() { console.log('I vaporized') },
onCondense: function() { console.log('I condensed') }
}
});
上面是作者给出的示例。
今天我们用红绿灯来学习这个项目。
let StateMachine = require('javascript-state-machine')
var fsm = new StateMachine({
init: 'red',
transitions: [
{ name: 'through', from: 'red', to: 'green' },
{ name: 'slow', from: 'green', to: 'yellow' },
{ name: 'stop', from: 'yellow', to: 'red' }
],
methods: {
onThrough: function () { console.log('绿灯请通行') },
onSlow: function () { console.log('黄灯请注意') },
onStop: function () { console.log('红灯请等待') },
}
})
.. 它创建具有当前状态属性的对象:
init:表示初始状态值,咱们这个实例中的初始状态值是红灯。
如果初始值不存在则会报错
通过fsm.state可以获取当前的状态值
console.log(fsm.state) // red
... 转换到其他状态的方法:
通过调取name可以进行转变
console.log(fsm.state); // red
fsm.through()
console.log(fsm.state); // green
但是,如果你打印的时候会发现,在red和green中间会打印“绿灯请通行”,这是因为在进行转变的时候,调用了onThrough,on,要记住name首字母大写。
但是如果我们当前状态值为red,我们必须按顺序进行下一个状态
console.log(fsm.state); // red
fsm.slow()
// 会报错
throw new Exception("transition is invalid in current state", transition, from, to, this.state);
^
{
message: 'transition is invalid in current state',
transition: 'slow',
from: 'red',
to: undefined,
current: 'red'
}
默认情况下,如果尝试触发当前状态下不允许的转换,状态机将引发异常。如果希望自己处理问题,可以定义自定义onInvalidTransition处理程序:
methods:{
onInvalidTransition: function (transition, from, to) {
console.error("transition not allowed from that state");
},
}
console.log(fsm.state); // red
fsm.slow()
// transition not allowed from that state
StateMachine也提供了一下的帮助器方法:
-
fsm.is(s)- 如果状态s是当前状态,则返回true -
fsm.can(t)- 如果从当前状态可以发生转换t,则返回true -
fsm.cannot(t)- 如果从当前状态无法发生转换t,则返回true -
fsm.transitions()- 返回当前状态允许的转换列表 -
fsm.allTransitions()- 返回所有可能转换的列表 -
fsm.allStates()- 返回所有可能状态的列表console.log(fsm.is('red')); // true console.log(fsm.can('through')); // tr console.log(fsm.cannot('slow')); // true console.log(fsm.transitions()); // [ 'through' ] console.log(fsm.allTransitions()); // [ 'init', 'through', 'slow', 'stop' ] console.log(fsm.allStates()); // [ 'none', 'red', 'green', 'yellow' ]
这就是这个库最基本的功能,当然它还可以有其他扩展功能:
- States and Transitions
- Data and Methods
- Lifecycle Events
- Asynchronous Transitions
- Initialization
- Error Handling
- State History
- Visualization
- State Machine Factory
- Upgrading from 2.x
今天就先写到这个,下次我们再来一起探讨一些进阶功能。