我正在尝试使用Apache scxml实现控制流。我的状态转换就像
<scxml initial="State1">
<state id = "State1"><transition event="event1" target="State2"></state>
<state id = "State2">
<transition event="event2" target="State3">
<transition event="event3" target="State4">
</state>
<state id = "State3">
<transition event="event4" target="State2">
</state>
<state id = "State4">
<transition event="event5" target="State2">
</state>
<state id = "State5"><transition target="State1">
</scxml>
作为状态机,它工作正常,工作没有任何问题。但我有几个要求,我在
中面临问题我必须检查每个状态中的外部事件,如果该事件为真,我必须转到循环的最后一个状态。实现这一目标的最佳方法是什么?
当我在state2
时,我可以通过state4
转到state5
或state3
。在检查条件后,我可以在state3
或state4
之后触发事件或从state5
更改状态吗?
上述两个问题似乎都有相同的解决方案,但我无法找出实施它们的最佳方法。
答案 0 :(得分:0)
检查外部事件[...],如果该事件为真[...],请转到周期的最后一个状态。
通过将所有状态包装在父包装器中并从那里转换,可以最优雅地完成此操作。例如:
<scxml xmlns="http://www.w3.org/2005/07/scxml" initial="state1">
<state id='all'>
<!-- this will always be tested, no matter which child state you are in -->
<transition event="externalevent" target="state5" />
<state id="state1"><!-- ... --></state>
<state id="state2"><!-- ... --></state>
<state id="state3"><!-- ... --></state>
<state id="state4"><!-- ... --></state>
<state id="state5"><!-- ... --></state>
</state>
</scxml>
当我在
state2
时,我可以通过state4
转到state5
或state3
吗?
这似乎是您描述的糟糕模式,但是,这是可能的。您需要在进入状态的路上设置一个标志,并使用该标志立即过渡。例如,使用简单的Lua datamodel(Apache SCXML不支持,但为了清楚起见,此处使用):
<datamodel>
<data id="bounceTo" expr="-1" />
</datamodel>
<state id="state2">
<transition event="bounce-3-4" target="state3">
<assign location="bounceTo" expr="4" />
</transition>
<transition event="bounce-3-5" target="state3">
<assign location="bounceTo" expr="5" />
</transition>
</state>
<state id="state3">
<transition cond="bounceTo==4" target="state4">
<assign location="bounceTo" expr="-1" />
</transition>
<transition cond="bounceTo==5" target="state5">
<assign location="bounceTo" expr="-1" />
</transition>
</state>
在Apache SCXML中设置,测试和清除数据值超出了我的想法。
然而,我必须问你为什么要这样做。在我看来,在转换本身上复制你可能想要的state3
的进入或退出动作似乎要好得多,并让这些转换直接针对状态4或5。