question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

chaining transitions

See original GitHub issue

Hey!

I’d like to chain transitions to keep each state simple and to explicitly map out the various states so that someone else can look at the state machine as a map of what the app does, under what conditions, and in what order.

The documentation states that _enter’s returns are ignored so im having to work around this.

I dont exactly understand why it is that _enter should not allow transitions. Would it undermine the concept of finite state machines?

At the moment in order to chain things, im having to do something like this:

const machine = fsm('idle', {
	idle: {
		click() {
			return 'clicked';
		}
	},
	clicked: {
		_enter() {
			if (get(userStore)) this.userInfoAvailable();
			else this.userInfoMissing();
		},
		userInfoMissing: 'userInfoMissing',
		userInfoAvailable: 'userInfoAvailable'
	},
	userInfoMissing: {
		_enter() {
			//do a thing
		}
	},
	userInfoAvailable: {
		_enter() {
			// do another thing
		}
	}
});

its not clear to me from the documentation if I could accomplish this in a less verbose way. Am I missing something?

ideally what this would look like is this:

const machine = fsm('idle', {
	idle: {
		click() {
			return 'clicked';
		}
	},
	clicked: {
		_enter() {
			if (get(userStore)) return 'userInfoMissing';
			else return 'userInfoAvailable';
		},
	},
	userInfoMissing: {
		_enter() {
			//do a thing
		}
	},
	userInfoAvailable: {
		_enter() {
			// do another thing
		}
	}
});

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
kenkunzcommented, Nov 30, 2021

See Store contract and svelte/store. Every time you call get(), you are

  • creating a new subscription to the store
  • which synchronously calls the subscriber with the current store value
  • unsubscribing
  • returning the value from the second step above

I think a better pattern would be to subscribe to the userStore directly, and invoke a userChange event on the FSM when the store calls your subscriber.

For example, after you have created your FSM, call userStore.subscribe(stateMachine.userChange). Within the FSM, include appropriate userChange actions for a given state where it’s needed. When the click event is invoked, your FSM already knows the user’s login / permission state, so it just responds to the click appropriately.

Your user store subscription and click events are two independent inputs on your FSM. Each one acts on the FSM and in some cases causes it to transition.

Note that if you are subscribing to the userStore directly as suggested above, you may need to also unsubscribe at some point – e.g., when the component that is using this FSM is destroyed (onDestroy). If the component is being used on a page in a context where it is never destroyed (e.g., it’s not an SPA and navigating away from the page causes a full document re-load), then you should be OK not calling unsubscribe.

Hope this helps!

0reactions
morungoscommented, Jun 9, 2022

I know this is closed, but I needed it, so I’ve made a first draft of an implementation. It does make a few small external changes, so I’ve not yet made it a pull request, but I’d be very very happy to do so if you’d like. It’s in a commit: https://github.com/morungos/svelte-fsm/commit/0955042122b95f94cfca9b62f574e5f23ed92200.

The principle is: use _enter() to possibly return a new state. If there is one, we generate a new _exit()/_enter() pair, and continue until we don’t get a value back from _enter(). At that point, if the new state is different from the old state, we can inform subscribers via a true event. it’s not ideal, but does what I need, and is close enough to automatic transitions in state charts to be useful.

The most consequential changes are:

  1. It now expects _enter() to return a meaningful value – this could be tweaked to signal differently, say via a passed function in the event metadata. Chances are, naively, this would break existing uses.
  2. The _enter() call is now before the subscribers are informed, not after. This is explicitly tested, so it’s serious. But I don’t think it’s necessarily wrong. My guess is this won’t break existing uses, though.

The benefit of this is that we can have internal states that aren’t communicated to Svelte or such, but which make the flow simpler than attempting to fold it into more complex actions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Chaining CSS Transitions - CodePen
Sometimes you want to use CSS animations but you don't want to use Javascript to create a simple hover effect. Here's the next...
Read more >
Using Multi-Step Animations and Transitions | CSS-Tricks
We can do this by chaining our transitions on each element where there are multiple properties to transition! /* Our box element */...
Read more >
Dynamically chained CSS Transitions | by Felix Blaschke
The basic pattern of a chained CSS Transition consists of 4 steps: Configure CSS Transition; Define the animation states; Create an animation controller;...
Read more >
Chained Transitions - GitHub Gist
This animation demonstrates the use of transition.transition and d3.active to create chained transitions. Chained transitions inherit the reference time of ...
Read more >
How to chain two CSS transitions on Javascript?
I am trying to make an animation where I translate a slideshow without a transition. Then translate the same slideshow but ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found