有限状态机

326 阅读2分钟

简介

  • 状态机库: JavaScript-state-machine
  • 安装: npm install --save-dev javascript-state-machine
  • 使用场景: 同时满足以下三种情况即可使用
    • 状态总数(state)是有限的
    • 任一时刻,只处在一种状态之中
    • 某种条件下,会从一种状态转变(transition)到另一种状态

大致用法

  1. 根据实际情况画出状态转移图
  2. 声明 StateMachine 实例且传递状态机的参数options
    • init: 状态初始值
    • transitions: 状态转移过程
    • methods: 状态转移后的钩子
    • data: 实例内的数据
  3. 根据情况进行状态间的转换,只需要执行 transitions 中相应的 name 方法
    • 如需要从 green 转变到 yellow,只需执行 fsm.warn() 即可
    • 而 onWarn 方法则在状态从 green 变为 yellow 后触发执行

案例: 红绿灯状态

const StateMachine = require('javascript-state-machine'); 

const fsm = StateMachine({
  init: 'green',
  transitions: [
    // 执行 fsm.warn() 时触发事件warn(green->yellow)
    { name: 'warn',  from: 'green',  to: 'yellow' },
    { name: 'stop', from: 'yellow', to: 'red' },
    { name: 'ready',  from: 'red',    to: 'yellow' },
    { name: 'go', from: 'yellow', to: 'green' }
  ],
  methods: {
    onBeforeWarn: function() { console.log('在warn事件发生之前触发') },
    onAfterWarn: function() { console.log('在warn事件发生之后触发') },
    onLeaveGreen: function() { console.log('在离开green状态时触发') },
    onEnterGreen: function() { console.log('在进入green状态时触发') },
    onInvalidTransition: function(transition, from, to) {
      throw new Exception("transition not allowed from that state");
    },
  }
});

查询当前状态与事件

  • fsm.state: 返回当前状态
  • fsm.is(s): 返回一个布尔值,表示状态s是否为当前状态
  • fsm.can(e): 返回一个布尔值,表示事件e是否能在当前状态触发
  • fsm.cannot(e): 返回一个布尔值,表示事件e是否不能在当前状态触发

事件钩子

可以为每个事件指定两个回调函数

  • onBeforeWarn: 在warn事件发生之前触发
  • onAfterWarn(可简写成onWarn): 在warn事件发生之后触发

状态钩子

可以为每个状态指定两个回调函数

  • onLeaveGreen: 在离开green状态时触发
  • onEnterGreen(可简写成onGreen): 在进入green状态时触发 可以为所有的状态指定通用的回调函数
  • onLeaveState: 离开任一状态时触发
  • onEnterState: 进入任一状态时触发

异步操作

异步操作结束,再发生状态改变(transition方法)

fsm.onLeaveGreen = function() {
  return new Promise(function(resolve, reject) {
    // 异步操作: fadeIn
    $('#menu').fadeIn('fast', resolve)
  })
};

错误处理

const fsm = StateMachine({
  methods: {
    /* onInvalidTransition: 当发生了当前状态不可能发生的事件时自动触发
     * 比如,当前状态是green,理论上这时只可能发生warn事件
     * 要是这时发生了stop事件,就会触发这个错误处理函数
    */
    onInvalidTransition: function(transition, from, to) {
      throw new Exception("transition not allowed from that state");
    },
  }
});

参考