JavaScript中有限状态机的简介

242 阅读6分钟

最近,在JavaScript领域有很多关于有限状态机的讨论。

有一个流行的库叫XState,在GitHub上有超过11000颗星,我最近遇到了它,而且我一直在Twitter和其他地方看到它。这是一个非常酷的项目。

我第一次见到有限状态机和自动机是在20年前的高中,然后我在大学的数字设计课程中再次见到它们。

这个数字设计课程是关于信息编码、布尔代数、组合网络、顺序电路、顺序状态机、算术电路、VHDL等等。

我发现应用于前端工程的有限状态机的主题相当惊人,我回到我的旧书中,看看是否能找到对它们的良好解释。

我确实找到了很多信息,当然,作为教科书,事情被弄得比需要的还要复杂(IMHO)。我喜欢简化事情,我决定为正常人写一点解释,而不是为通过考试而写的理论性或任何东西。你可以在现实世界中应用的东西。

状态机

在研究什么是有限状态机之前,我想首先介绍一下什么是状态机。

世界上到处都是状态机。你可以到处看到它们,但也许你并没有想到它们是这样的。读完本教程后,我相信你会指出现实世界中的物体,对你的朋友说 "那是一个状态机"(取决于你朋友的书呆子水平)。

最流行和最常见的例子是交通灯

在任何时间点上,交通信号灯都有一个确定的状态。通常情况下,它要么。

  • 绿灯亮起,其他两个灯关闭
  • 红灯亮起,其他两个灯熄灭
  • 黄灯亮起,其他两个灯熄灭

Traffic lights

(有些信号灯略有不同,但为了这个例子,我们并不关心)

在状态机的术语中,灯的开启或关闭被称为输出

这3种情况中的每一种都被称为状态。当交通信号灯收到一个输入时,它将改变状态,通常只是一个固定的计时器,它决定了交通灯应该在多长时间内是绿色、黄色和红色。

在这种情况下,定时器就是系统的输入。有些信号机有一个按钮,行人可以按下,使红色显示为汽车,这将是另一个输入。

在状态机中,状态只有在响应输入时才能改变(我们有一个过渡)。

有限状态机

我们的交通灯状态机被说成是有限的,因为我们有有限数量的状态。

有些系统可能有无限多的状态。

比如世界生态系统模型,或者昆虫的生命。我们不能用有限的状态数来定义它。

但是交通灯呢?那是一个简单的东西,它有3个状态,就像我们上面说的。

我们还可以用很多有限状态机的例子。

  • 自动售货机
  • 地铁入口旋转门
  • 一个供暖系统
  • 自动地铁系统
  • 自动驾驶汽车系统
  • 电梯

但让我们坚持以交通灯为例,它非常简单,我们可以很容易地进行推理。

建立状态机模型

当然,交通灯并不是孤立存在的。那是另一个有限状态机,它包含了多个不同的有限状态机,每个交通灯设备安装在十字路口的每条路的两侧,它们同步工作。

Crossroads

现在不要去想它了。让我们专注于1个单一的交通信号灯。

正如我们上面所说的,我们有3个状态,可以称为绿色、红色、黄色。

The 3 states

我们有一个初始状态。假设我们的交通信号灯开始时,当我们重置它们时,处于green

Initial state

我们有一个计时器,在50秒的绿色状态后,将信号灯移到yellow 。我们有8秒的yellow 状态,然后我们移动到red 状态,并在那里停留32秒,因为那条路是次要的,它应该有更少的绿色时间。在这之后,信号灯又回到了绿色状态,这个循环无限期地继续下去,直到电力停止,信号灯再次获得电力时复位。

总的来说,我们有一个90秒的周期。

这就是我们的建模方式。

The model

我们也可以用状态转换表来建模,它显示了机器目前所处的状态,它收到的输入是什么,下一个状态是什么,以及输出

状态输入下一个状态输出
绿色定时器50秒黄灯绿灯亮,其他灯灭
黄灯定时器8秒红灯黄灯亮,其他灯灭
红灯定时器32秒绿灯红灯亮,其他灯灭

在我们的简单案例中,给定机器的任何状态,我们只有一个逻辑状态可以进入,所以我做的表格和图表是非常非常简单的。

但是,当你的系统开始变得更加复杂时,有这样的图表和分析是非常有帮助的,因为你可以对你的应用程序进行推理,而不是简单地把所有东西都放在脑子里。

一个具有更复杂的状态转换的有限状态机

上面的例子是非常简单的。现在让我们为另一个有限状态机建模。

我们的现实世界是这样的:我们有一个房子,有一扇门,两个按钮和三个灯。

在默认状态下,灯都是关着的。

lights

当你进入房子时,你可以按下2个按钮中的一个,p1p2 。当你按下其中任何一个按钮时,l1 灯就会打开。

想象一下,这是入口处的灯,你可以把你的外套脱掉。一旦你完成了,你决定你想进入哪个房间(例如厨房或卧室)。

如果你按下按钮p1l1 关掉,l2 打开。相反,如果你按下按钮p2l1 关闭,l3 打开。

再按一次这两个按钮中的任何一个,p1p2 ,当前开启的灯就会关闭,我们就会回到系统的初始状态。

这个有限状态机比第一个稍微复杂一些,因为这一次我们可以根据输入的情况有多条路线。

让我们对此进行建模。

我们基本上有4个状态。

  • 没有开灯
  • l1 开启
  • l2 开启
  • l3 开启

model lights

我们有2个输入。

  • p1
  • p2

如果我们从初始状态开始,并试图模拟所有可能发生的事情,这取决于输入如何随时间被触发,我们最终会得到。

State transitions

我们可以用这个表来总结一下。

状态输入下一个状态
没有开灯p1 已按下l1 开启
无灯开启p2 已按下l1 开启
l1 开启p1 已按下l2 开启
l1 开启p2 已按下l3 开启
l2 开启p1 已按下无灯开启
l2 开启p2 已按下不开灯
l3 开启p1 已按下不开灯
l3 开启p2 已按下不开灯

这是一个简短的解释,但也许它使事情变得 "简单"。