【问题标题】:Looped invoke in scxml eventscxml 事件中的循环调用
【发布时间】:2018-10-08 09:17:00
【问题描述】:

我有一个带有“invoke”元素的 scxml 事件。当事件被调用时,这个调用元素会更新数据模型元素。我怎样才能使这种情况定期发生?例如,是否可以每秒定期调用此调用?或者也许每秒都过渡到事件?

后者的问题是,如果我在调用的 finalize 部分放置一个转换,调用它自己,它似乎不会多次调用调用部分。

【问题讨论】:

    标签: recursion scxml apache-commons-scxml


    【解决方案1】:

    我首先想介绍一下<invoke> 的背景。 <invoke> 被放置为 <state> 的子代。它在进入状态时启动子状态机会话,并在退出状态时停止会话。此外,如果子会话进入<final> 状态,则在父会话上调度done.invoke.invokeid 事件。您可以在父状态的转换中使用此done.invoke.invokeid 事件,以在子会话终止时强制父状态退出。最后,父子状态可以通过<send>相互通信。父母可以使用<send>与孩子沟通,target属性设置为_invoke_invokeid,孩子可以通过<send>与父母沟通,target属性设置为_parent

    现在,回答你的问题:

    当事件被调用时,这个调用元素会更新数据模型元素。

    我认为您对此概念化的方式可能存在问题,因为调用的会话有自己的数据模型(也就是说,它自己的内存)。您可以使用<param> 绑定子会话的初始数据模型值,但您不能真正在父会话和子会话之间共享内存。这意味着您不能直接在子会话中使用例如更新父会话中的数据模型。 <assign><script> 标签。

    子会话在父会话中更新数据模型的唯一方法是通过传递事件(例如<send event="update" target="_parent"><param name="dataToUpdate" expr="dataToUpdate"/></send>)与父会话通信。然后父级需要有一个<transition> 元素,以便它可以处理从子会话发送的事件,例如<transition event="update"><assign location="dataToUpdate" expr="_event.dataToUpdate"/></transition>.

    这导致了<invoke> 是否是定期更新数据模型的最佳、最简单方法的问题。例如,将数据模型更新逻辑放在<parallel> 状态的子项中可能会更简单。这样,您可以使用<assign> 直接更新数据模型。

    我怎样才能让这种情况定期发生?例如,是否可以每秒定期调用此调用?或者也许每秒都切换到事件?

    要定期调用会话,您将进入和退出包含<invoke> 元素的状态。以下(未经测试的)代码可能会起作用:

    <state id=invokeParent">
      <!-- this is some data that you want the child session to update in the parent session -->
      <datamodel>
        <data id="dataToUpdate" />
      </datamodel>
      <onentry>
        <send event="loop" delay="1s"/> <!-- send the 'loop' event every second to loop in invokeParent -->
      </onentry>
      <transition event="loop" target="invokeParent" /> <!-- this transition will exit and re-enter the state, restarting the invoked session -->
      <transition event="done.invoke.myInvoke" target="invokeParent" /> <!-- also loop if the invoked session terminates -->
      <invoke id="myInvoke" type="scxml" src="file:test276sub1.scxml"/> <!-- this is the invoke -->
      <!-- this targetless transition handles the update event sent from the child session to the parent to update the parent's datamodel -->
      <transition event="update">
        <assign location="dataToUpdate" expr="_event.dataToUpdate"/>
      </transition>
    </state>
    

    后者的问题是,如果我在调用的 finalize 部分放置一个转换,调用它自己,它似乎不会多次调用调用部分。

    我不相信transitionfinalize 的合法子代。 finalize 旨在包含可执行内容(例如scriptassign),允许您在子会话发送的事件被父会话处理之前对其进行操作。

    https://www.w3.org/TR/scxml/#finalize

    【讨论】:

    • 哇,这是一个详细的回复。谢谢,它真的为我澄清了一些事情。我说我在 finalize 中放置了一个过渡是错误的。我实际上所做的是引发了一个事件,该事件触发了我的 finalize 中的转换。非常感谢
    • 在上面的代码中,是什么引发了“update”事件? PS。我相信我已经尝试过类似于上述的解决方案,但由于某种原因,调用仅在第一次“迭代”时输入......
    • 回复:引发“更新”事件的原因。在调用的会话中,您可以像这样将事件发送到父会话:&lt;send event="update" target="_parent"&gt;&lt;param name="dataToUpdate" expr="dataToUpdate"/&gt;&lt;/send&gt;
    • @Joker 随时在 SCION-SCXML 聊天室与我联系:gitter.im/SCION-SCXML/Lobby
    • @Joker 或者您可以使用 scxml 标签将您的问题发布到 stackoverflow
    猜你喜欢
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 2023-02-11
    • 1970-01-01
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多