poshest
poshest

Reputation: 4237

AngularJS Comet ("real-time") app two way inter-module communication

I have a large complex AngularJS Comet application ("real-time"). Clients send data to the server, and also receive notifications from the server about events other users have initiated.

In its simplest form, the app has these client-side components ("Service" below could be AngularJS .service or .factory, whatever)

Calls can go both directions

What is the best architecture for two-way inter-module communication in this case?

Here's what I think are the options. Please suggest other good ones if I've left them out.

  1. Use the circular dependency fudge. Everywhere I read it seems we shouldn't be doing that, including Lu4 in his "fudge" answer. On the other hand, doing this means you can have method calls in both directions, keeping inter-module communication consistent throughout the app.
  2. Use dependency injection and method calls in one direction, and events in the other direction. There's some opposition to over-using events. Is this a case of over-using?
  3. Use events in both directions. Moves closer to "over-use", but keeps inter-module communication consistent throughout the app.
  4. Use a Mediator pattern, ie have a central orchestrating service that coordinates in both directions. I'm not sure how this is different or better than using events, wherein $rootScope becomes the "mediator" against which all events and their callbacks are registered.
  5. Some kind of long-polling between modules, so that, eg the [Object] Controller makes a call to [Object] Service, which returns a promise and in turn calls Socket Service that also returns a promise, and when Socket Service receives some data, the promise resolves back up the chain, at which point [Object] Controller initiates another request.

Upvotes: 1

Views: 994

Answers (1)

jan.vogt
jan.vogt

Reputation: 1817

A clean solution would be to use classical DI for the user initiated direction. Since your [Object] Service contains the model you only need to update that (if you implementation is otherwise clean, i.e. you use the injected model object everywhere).

So the problem is reduced to how to get the new updates from your Socket Service to the [Object] Service. Since your Socket Service actually should not know about your Models Details injection of the models is not a reasonable solution (leave alone the so created circular dependency). Recieving an update from a server for anything in your client app is in in the very definition an event (can occure at any time), so I think it is very reasonable to get the $RootScope in your SocketService and broadcast it. On this event your [Object] Services take than care for updating the models based on the new information.

If you have many services and usually the server initiated events are only relevant to one or very few of them, a possible optimization would be to sent the a field from the server which models are affected by this update. This is reasonable, since the server knows about the models already and it enables the Socket Service to broadcast updateFor:xxx events without knowing about what xxx means. The respective [Object] service then listens only to the updateFor:[Object] event. But as always with optimizations, do not do them if the easy way already works for you.

Upvotes: 1

Related Questions