JavaScript与有限状态机

 有限状态机(Finite-state machine)是一个非常有用的模型,可以模拟世界上大部分事物。

  简单说,它有三个特征:

* 状态总数(state)是有限的。
* 任一时刻,只处在一种状态之中。
*
某种条件下,会从一种状态转变(transition)到另一种状态。

  它对JavaScript的意义在于,很多对象可以写成有限状态机。

  举例来说,网页上有一个菜单元素。鼠标悬停的时候,菜单显示;鼠标移开的时候,菜单隐藏。如果使用有限状态机描述,就是这个菜单只有两种状态(显示和隐藏),鼠标会引发状态转变。

  代码可以写成下面这样:





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

var
menu = {

    // 当前状态

    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;

      }

    }

  };

  可以看到,有限状态机的写法,逻辑清晰,表达力强,有利于封装事件。一个对象的状态越多、发生的事件越多,就越适合采用有限状态机的写法。

  另外,JavaScript语言是一种异步操作特别多的语言,常用的解决方法是指定回调函数,但这样会造成代码结构混乱、难以测试和除错等问题。有限状态机提供了更好的办法:把异步操作与对象的状态改变挂钩,当异步操作结束的时候,发生相应的状态改变,由此再触发其他操作。这要比回调函数、事件监听、发布/订阅等解决方案,在逻辑上更合理,更易于降低代码的复杂度。

  下面介绍一个有限状态机的函数库Javascript Finite State
Machine
。这个库非常好懂,可以帮助我们加深理解,而且功能一点都不弱。

  该库提供一个全局对象StateMachine,使用该对象的create方法,可以生成有限状态机的实例。





1

var
fsm = StateMachine.create();

  生成的时候,需要提供一个参数对象,用来描述实例的性质。比如,交通信号灯(红绿灯)可以这样描述:





1

2

3

4

5

6

7

8

9

10

11

12

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‘
}

    ]

  });

  交通信号灯的初始状态(initial)为green,events属性是触发状态改变的各种事件,比如warn事件使得green状态变成yellow状态,stop事件使得yellow状态变成red状态等等。

  生成实例以后,就可以随时查询当前状态。





1

2

3

4

* fsm.current :返回当前状态。

* fsm.is(s) :返回一个布尔值,表示状态s是否为当前状态。

* fsm.can(e) :返回一个布尔值,表示事件e是否能在当前状态触发。

* fsm.cannot(e) :返回一个布尔值,表示事件e是否不能在当前状态触发。

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





1

2

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

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

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





1

2

* onleavegreen :在离开green状态时触发。

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

  假定warn事件使得状态从green变为yellow,上面四类回调函数的发生顺序如下:onbeforewarn →
onleavegreen → onenteryellow → onafterwarn。

  除了为每个事件和状态单独指定回调函数,还可以为所有的事件和状态指定通用的回调函数。





1

2

3

4

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

* onleavestate :离开任一状态时触发。

* onenterstate :进入任一状态时触发。

* onafterevent :任一事件结束后触发。

  如果事件的回调函数里面有异步操作(比如与服务器进行Ajax通信),这时我们可能希望等到异步操作结束,再发生状态改变。这就要用到transition方法。





1

2

3

4

5

6

fsm.onwarn = function(){

    light.fadeOut(‘slow‘, function() {

      fsm.transition();

    });

    return
StateMachine.ASYNC;

  };

  上面代码的回调函数里面,有一个异步操作(light.fadeOut)。如果不希望状态立即改变,就要让回调函数返回一个StateMachine.ASYNC对象,表示状态暂时不改变;等到异步操作结束,再调用transition方法,使得状态发生改变。

  Javascript Finite State
Machine还允许指定错误处理函数,当发生了当前状态不可能发生的事件时自动触发。





1

2

3

4

5

6

7

var
fsm = StateMachine.create({

    // ...

    error: function(eventName, from, to, args, errorCode, errorMessage) {

      return
‘event ‘ + eventName + ‘: ‘
+ errorMessage;

    },

    // ...

  });

  比如,当前状态是green,理论上这时只可能发生warn事件。要是这时发生了stop事件,就会触发上面的错误处理函数。

  Javascript
Finite State Machine的基本用法就是上面这些,更详细的介绍可以参见它的主页

JavaScript与有限状态机,布布扣,bubuko.com

时间: 2024-10-10 21:14:46

JavaScript与有限状态机的相关文章

【转】【修真院“善良”系列之十八】WEB程序员从零开始到就业的全资料V1.0——只看这一篇就够了!

这是两年以来,修真院收集整理的学习资料顺序.以CSS15个任务,JS15个任务为基础,分别依据要完成任务的不同的技能点,我们整理出来了这么一篇在学习的时候需要看到的资料. 这是Version 1.0,接下来会优化和更新到2.0.现在只有WEB,接着会推出Java. 任务地址在这里. 任务体系是从简单到难,官网提供了更多更详细的资料. 资料 css部分任务1:九宫格--用html+css制作一个网页通过这个任务能学到:1.网页是由什么组成的:2.如何生成一个网页:3.如何访问一个网页:4.html

React 源码剖析系列 - 生命周期的管理艺术

目前,前端领域中 React 势头正盛,很少能够深入剖析内部实现机制和原理. 本系列文章 希望通过剖析 React 源码,理解其内部的实现原理,知其然更要知其所以然. 对于 React,其组件生命周期(Component Lifecycle)是它的核心概念,本文从源码入手,来剖析 React 生命周期的管理艺术. 阅读本文需要对 React 有一定的了解,如果你不知何为组件的生命周期,请详读 React 生命周期的文档. 如果你对 React 组件的生命周期存在些许疑惑,如生命周期如何顺序管理:

试试用有限状态机的思路来定义javascript组件

本文是一篇学习性的文章,学习利用有限状态机的思想来定义javascript组件的方法,欢迎阅读,后续计划会写几篇专门介绍自己利用有限状态机帮助自己编写组件的博客,证明这种思路对于编程实现的价值,目前正在积极构思中.本文代码下载 1. 有限状态机概述 简单说,有限状态机是一种模型,模型都用来模拟事物,能够被有限状态机这种模型模拟的事物,一般都有以下特点: 1)可以用状态来描述事物,并且任一时刻,事物总是处于一种状态: 2)事物拥有的状态总数是有限的: 3)通过触发事物的某些行为,可以导致事物从一种

谈谈Javascript异步编程以及新的实现方法--Promise

最近看到好多文章都在讲promise,为什么现在异步编程会受到如此重视?又为什么异步编程要选择Promise呢? 先来说说第一个问题,异步编程能受到如此重视很大原因是因为javascript正在逐渐走向标准化.规范化(MVC,模块,OOP),所以一些传统编程领域的一些规范化约束发挥的作用也越来越大了,而且javascript本身就是围绕"异步"来进行的,无论是浏览器端还是node服务器端,大多数的API都是通过"事件"来将请求和返回值分离的.简单来说:javascr

阮一峰老师JavaScript课程学习笔记

1.switch采用的是严格相等运算符 2.break和continue都具有跳转作用,break语句跳出循环,continue用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环. 3.JavaScript内部所有数字都是以64位浮点数形式存储,涉及小数的运算和比较需要特别小心. (-1)^符号位 * 1.xx...xx * 2^指数位 4.NaN是JavaScript的特殊值,表示"非数字(Not a Number)",主要出现在将字符串解析成数字出错的场合.NaN不等于任何值

ASYNC PROGRAMING IN JAVASCRIPT[转]

本文从异步风格讲起,分析Javascript中异步变成的技巧.问题和解决方案.具体的,从回调造成的问题说起,并谈到了利用事件.Promise.Generator等技术来解决这些问题. 异步之殇 NON-BLOCKING无限好? 异步,是没有线程模型的Javascript的救命稻草.说得高大上一些,就是运用了Reactor设计模式1. Javascript的一切都是围绕着“异步”二子的.无论是浏览器环境,还是node环境,大多数API都是通过“事件”来将请求(或消息.调用)和返回值(或结果)分离.

JavaScript异步交互

JavaScript 异步编程简介 回调函数和异步执行 所谓的异步指的是函数的调用并不直接返回执行的结果,而往往是通过回调函数异步的执行. 我们先看看回调函数是什么: var fn = function(callback) { // do something here ... callback.apply(this, para); }: var mycallback = function(parameter) { // do someting in customer callback }: //

JavaScript对象状态

有限状态机(Finite-state machine)是一个非常有用的模型,可以模拟世界上大部分事物. 简单说,它有三个特征: * 状态总数(state)是有限的. * 任一时刻,只处在一种状态之中. * 某种条件下,会从一种状态转变(transition)到另一种状态. 它对JavaScript的意义在于,很多对象可以写成有限状态机. 举例来说,网页上有一个菜单元素.鼠标悬停的时候,菜单显示:鼠标移开的时候,菜单隐藏.如果使用有限状态机描述,就是这个菜单只有两种状态(显示和隐藏),鼠标会引发状

Javascript MVC 学习笔记(二) 控制器和状态

今天进入第二个部分:控制器. 控制器和状态 从以往的开发经验来看,我们都是将状态保存在服务器的session或者本地cookie中,但Javascript应用往往被限制在单页面,所以我们也可以将状态保存在客户端的内存里面.保存在内存还意味着能带来更快的界面响应. 在MVC里面,状态都是保存在控制器里的,控制器相当于应用中视图和模型的纽带.当加载页面的时候,控制器将事件处理程序绑定在视图里,并适时处理回调,以及和模型必要的对接. 控制器是模块化的而且非常独立,理想状况下不应该定义任何全局变量,而是