33

有人知道状态机的任何 javascript 实现吗?我的目标是设置一个状态机实现,将事件绑定到状态转换。因此,如果用户单击按钮,则状态将被更改,并且此状态可能会在要更改的对象中定义某些值。

我希望这是一个状态机,因为会有一个规则 json 文件,允许在调用某些事件时指示各种对象的哪些值发生变化。因为这将在文件中进行结构化,所以我认为将这些信息解析为状态机对象会很容易。

4

10 回答 10

37

js 中有两个用于有限状态机的主要库:

1/ Machina:非常有据可查的示例,支持两个开箱即用的 JavaScript 消息总线提供程序:postal.jsamplify.js

2/ Javascript 状态机:更简单易用,非常适合“基本”用途。

于 2013-03-26T15:58:50.247 回答
6

我最近在 JS 中构建了一个状态机实现,这当然是最容易配置的,这要归功于它的转换 DSL:

transitions: [
  'next    : intro > form > finish',
  'back    : intro < form           < error',
  'error   :         form >           error',
  'restart : intro        < finish'
]

它在配置和事件处理程序分配方面非常灵活,您可以在运行时添加和删除状态,暂停和恢复转换,挂钩到大量事件,以及 jQuery 和响应式框架(如 Vue)的帮助程序:

状态机演示

文档和大量演示在这里:

于 2016-12-23T20:07:40.580 回答
4

我的状态机的一点点提升:stateflow 我刚刚创建了我自己的状态机,因为我没有找到对我来说足够简单的状态机。

流是用一个 js 对象定义的,其中属性是状态名称,值是另一个具有以下属性的 js 对象。

  • 类型:开始、结束或状态(默认)。
  • 动作:将状态实例对象设置为此的函数,也可以命名为先前注册的动作或另一个流定义,在这种情况下它是一个子流。
  • on:属性是要匹配的事件,值是要转到的下一个状态

简单的例子

var stateflow = require('stateflow');
var flow = new stateflow.StateFlow({
   a: {
       type:'begin',
       action: function(complete) {
           // do something
           complete('done');    
       },
       on: {
           done:'b',
           again:'a'
       }
   }, 
   b: {
       type:'end',
       action: function(complete) {
           complete('finished');
       }
   }
});
flow.start(function(event) {
   console.log('flow result:', event);
});

在 git https://github.com/philipdev/stateflow或通过 npm查看

于 2015-01-26T18:58:32.907 回答
3

尝试查看https://github.com/steelbreeze/state.js - 它支持 UML 2 规范中描述的大部分状态机语义,同时仍然具有高性能。文档的方式并不多,但是示例和测试应该提供很好的参考。

于 2013-06-06T08:45:53.273 回答
2

您会发现使用 jQuery 设计的库似乎可以满足您的需求并自动为您绑定事件:

于 2014-09-03T23:33:55.940 回答
1

我选择 js-fsm 微型库。

特征

  • 基于状态的 FSM 描述。由一个和一个状态转换数组组成的状态。
  • 从事件过渡。多个事件定义 ORed 事件。
  • 从条件过渡。条件是一个键:应该在条件对象上匹配的值对。多个键、值对定义了 AND 条件。多个条件定义 ORed 条件
  • 每个转换都可以选择调用动作或多个动作。动作可以选择有参数或成为 this 的成员。
  • 状态机可以混合(作为混合)到现有对象或构造函数的原型。为此提供了一种方法。
  • 如果在此存在或提供了日志方法,则状态机可以选择记录。
  • 支持 AMD 和 Node 模块。
  • 使用 QUnit 进行单元测试。

js-fsm github 页面。

于 2014-03-28T17:31:14.497 回答
1

我想我也会谈谈我自己的状态机库。两年前我遇到了这个 SO 问题,找不到任何符合我要求的东西,所以我写了state-transducer

API 的主要目标是:

  • 功能性 API,完全没有效果,具有封装的内部状态
  • 通用性和可重用性(没有提供适应特定用例或框架的规定)
  • 必须可以在当前设计之上添加并发和/或通信机制
  • 必须能够顺利集成到 React、Angular 和您的流行框架中

它用于建模用户界面,转变用户流程。

用户流

进入状态机

fsm

于 2019-01-16T14:24:43.173 回答
0

您可能会发现这个使用库:

https://www.npmjs.com/package/mistic

免责声明:我维护它。

于 2015-07-17T10:19:23.183 回答
0

AsyncMachine是另一种不太正统的 JS 状态机方法(我是作者)。它是相关的并且支持同时处于活动状态的多个状态。这里有一些代码可以回答您最初的问题 - 单击按钮后,在新状态和上下文对象上的属性方面会产生副作用:

const {
  machine
} = asyncmachine
// define states & relations
const state = {
  Clicked: {
    add: ['ShowFooter']
  },
  ShowFooter: {}
}
const example = machine(state)
// define handlers
example.Clicked_state = function() {
  this.timeout = setTimeout(
    this.dropByListener('Clicked'), 3000)
}

function render() {
  console.log('render')
  // get all the active state as class names
  const classes = example.is().join(' ')
  console.log(classes)
  document.getElementById('content').innerHTML = `
    <div class="${classes}">
      <button>CLICK</button>
      <footer>FOOTER</footer>
    </div>
  `
}
document.getElementById('content').addEventListener(
  'click', example.addByListener('Clicked'))
// bind render to any state change
example.on('tick', render)
render()
.Clicked button {
  background: red;
}

footer {
  display: none;
}

.ShowFooter footer {
  display: block
}
<script src="https://unpkg.com/asyncmachine@3.4.1/dist/asyncmachine.umd.js"></script>
<div id='content' />

还有一个检查员可以可视化您的机器的工作方式(通过时间旅行),例如:

在此处输入图像描述

于 2018-09-25T03:15:50.670 回答
0

我使用过xtstate,它几乎解决了问题中发布的所有问题。它有一个很棒的可视化工具试试看。

于 2020-01-07T05:30:41.040 回答