Looped invoke в событии scxml
У меня есть событие scxml с элементом "invoke". Этот элемент invoke обновляет элементы модели данных при вызове события. Как я могу сделать это периодически? Можно ли периодически вызывать этот вызов, например, каждую секунду? Или, возможно, переходить на событие каждую секунду?
Проблема с последним состоит в том, что, если я помещаю переход в раздел finalize вызова, вызывающего себя, он, кажется, не вызывает раздел invoke более одного раза.
1 ответ
Сначала я хотел предоставить некоторые сведения о <invoke>
, <invoke>
как ребенок <state>
, Он запускает сеанс дочернего конечного автомата при входе в состояние и останавливает сеанс при выходе из состояния. Кроме того, если дочерний сеанс вводит <final>
состояние, то done.invoke.invokeid
событие отправляется на родительский сеанс. Вы можете использовать это done.invoke.invokeid
событие при переходе в родительское состояние, чтобы принудительно завершить родительское состояние после завершения дочернего сеанса. Наконец, родительское и дочернее состояния могут общаться друг с другом через <send>
, Родитель может общаться с ребенком, используя <send>
с target
атрибут установлен в _invoke_invokeid
и ребенок может общаться с родителем через <send>
с target
атрибут установлен в _parent
,
Теперь на ваши вопросы:
Этот элемент invoke обновляет элементы модели данных при вызове события.
Я думаю, что может быть проблема с тем, как вы это поняли, потому что вызываемый сеанс имеет свою собственную модель данных (то есть, свою собственную память). Вы можете привязать начальные значения модели данных дочернего сеанса, используя <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 вызова, вызывающего себя, он, кажется, не вызывает раздел invoke более одного раза.
Я не верю transition
является законным ребенком finalize
, finalize
должен содержать исполняемый контент (например, script
, assign
), которые позволяют вам манипулировать событиями, отправленными дочерним сеансом, прежде чем они будут обработаны родительским сеансом.