有人知道状态机的任何 javascript 实现吗?我的目标是设置一个状态机实现,将事件绑定到状态转换。因此,如果用户单击按钮,则状态将被更改,并且此状态可能会在要更改的对象中定义某些值。
我希望这是一个状态机,因为会有一个规则 json 文件,允许在调用某些事件时指示各种对象的哪些值发生变化。因为这将在文件中进行结构化,所以我认为将这些信息解析为状态机对象会很容易。
有人知道状态机的任何 javascript 实现吗?我的目标是设置一个状态机实现,将事件绑定到状态转换。因此,如果用户单击按钮,则状态将被更改,并且此状态可能会在要更改的对象中定义某些值。
我希望这是一个状态机,因为会有一个规则 json 文件,允许在调用某些事件时指示各种对象的哪些值发生变化。因为这将在文件中进行结构化,所以我认为将这些信息解析为状态机对象会很容易。
js 中有两个用于有限状态机的主要库:
1/ Machina:非常有据可查的示例,支持两个开箱即用的 JavaScript 消息总线提供程序:postal.js和amplify.js。
2/ Javascript 状态机:更简单易用,非常适合“基本”用途。
我最近在 JS 中构建了一个状态机实现,这当然是最容易配置的,这要归功于它的转换 DSL:
transitions: [
'next : intro > form > finish',
'back : intro < form < error',
'error : form > error',
'restart : intro < finish'
]
它在配置和事件处理程序分配方面非常灵活,您可以在运行时添加和删除状态,暂停和恢复转换,挂钩到大量事件,以及 jQuery 和响应式框架(如 Vue)的帮助程序:
文档和大量演示在这里:
我的状态机的一点点提升:stateflow 我刚刚创建了我自己的状态机,因为我没有找到对我来说足够简单的状态机。
流是用一个 js 对象定义的,其中属性是状态名称,值是另一个具有以下属性的 js 对象。
简单的例子
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);
});
尝试查看https://github.com/steelbreeze/state.js - 它支持 UML 2 规范中描述的大部分状态机语义,同时仍然具有高性能。文档的方式并不多,但是示例和测试应该提供很好的参考。
您会发现使用 jQuery 设计的库似乎可以满足您的需求并自动为您绑定事件:
我选择 js-fsm 微型库。
特征
我想我也会谈谈我自己的状态机库。两年前我遇到了这个 SO 问题,找不到任何符合我要求的东西,所以我写了state-transducer。
API 的主要目标是:
它用于建模用户界面,转变用户流程。
进入状态机
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' />
还有一个检查员可以可视化您的机器的工作方式(通过时间旅行),例如: