ifandelse / machina.js

js ex machina - finite state machines in JavaScript
http://machina-js.org/
Other
1.93k stars 147 forks source link

BehavioralFsm event emitter and clients #107

Closed kkirby closed 6 years ago

kkirby commented 9 years ago

Hello,

I had a question about how BehavioralFsm emits events. I was reading the code and saw that all events from any client are emitted on the BehavioralFsm instance (which makes sense). But let's say I have 200 instances of a class that utilize a BehavioralFsm, and I want to listen to transition events. Whenever any statemachine transitions, all listeners will be called even if they don't care so much because they aren't concerned with the Fsm that transitioned. I know you could do an if check on the client event argument property to see if it is equal to this, but having to run that check 200 times on a single event is a bit intense and unnecessary logic. Is there anyway around this? Perhaps a method signature like on(client,event)? I'm pretty sure it doesn't exist, but would machina.js give open arms to a pull request that implemented this functionality? If so, are there any gotchas I should know about before implementing such functionality?

I would was thinking of implementing it using a WeakMap and when an emitEvent was called, the client would be looked up in the WeakMap to determine the listeners.

j-ulrich commented 9 years ago

having to run that check 200 times on a single event is a bit intense and unnecessary logic

IMO, that's not what the current API is intending. Normally, you would attach only one listener for all FSMs. Not one listener per FSM. In case you need to treat the different FSMs differently, you would then need to have an if/else or switch statement in the listener. But that seems like a code smell because if the FSMs are of the same type (i.e. same BehavioralFSM) then it should not be necessary to treat them differently. Or the listener could simply call a method on the client and each client could implement that method as appropriate. That would be more object-oriented. For example:

var myBehavioralFsm = new machine.BehavioralFsm({
    // ...
});
myBehavioralFsm.on('transition', function(event) {
    event.client.onTransition();
});
ifandelse commented 9 years ago

@kkirby Hey - just wanted to drop you a note to say I plan to follow up with a reply, just been a crazy week! Once I get a second to actually sit down and think I'll touch base! :-)

ifandelse commented 6 years ago

Aaaand 2 years just flew by in an instant. I wish I could pretend I'm a time traveler, but alas, #146 explains that's not the case. 😺

For our future fellow devs that find themselves with similar questions, my current recommendation is along the lines of what @j-ulrich suggested: attach one listener to the behavioral FSM and then you can control the responsibilities from there. I'm not opposed to revisiting this issue in the future - but some real world use cases would be super helpful!