What is considered best practice for calling/triggering methods on one A-Frame Components from another?

As an example, I have a component called table and a System game which listens for a SocketIO event containing a list of winners (players sat at the table). The game system effectively emits the same event it receives so that each A-Frame component can listen for the ones they need. In my case, when the table "hears" the event emitted by the game System that contains the list of winners, I loop through each and highlight the winning player. At the moment my crude implementation is just to have the table component add some text to the element that has the same id as the corresponding player. This works, but at some point I'd like to call a function on the player component that could do a variety of things (e.g. play a sound, animation, change colour, etc.).

I can see there are a couple of approaches to achieving this:

  1. Get the table to emit an event for each winning player in a way that the player component can listen for it and do whatever it needs.

OR

  1. Call a function directly on the player component from the table component by finding the element and then doing something like playerEl.playWinningAnimation()

Are either of these considered particularly "bad practice"? What are the reasons for one approach over the other?


Solution 1:

I generally prefer emitting events, over direct function calls. Some benefits:

  • If the other component is not initialized yet, you don't get a crash.
  • If you want to fan info out to multiple entities it is much easier.
  • It may not be obvious that changing a function within a component might break things outside that component, whereas events are clearly an external interface, so you're much less likely to imagine you can change them without breaking things. Easier for testing individual components (due to looser coupling).

That said, there are cases where a function call direct to a component is justified.

There's a few examples in core A-Frame, e.g. on Raycaster. https://aframe.io/docs/1.2.0/components/raycaster.html#methods

Typically the main reason to use a function rather than events for inter-component comms is when you need to get an answer/data back. Maybe also for performance reasons (I've seen concerns expressed about the cost of DOM events, but I don't have any exact quantification of this. In general I think if it's outside a tick() function, and not happening 1000s of times, I expect DOM events are just fine).

If it's a 1-way communication, and not happening super-frequently, I think I'd pretty much always go for an event.