1

I'm playing with angularjs doing some simple stuff. I wanted to incorporate some real time messaging like PubNub, PubSub or Pusher. Basically I have it working, but it seems too cumbersome in some areas. Maybe you can show me a better way.

Ok, so here is my working jsfiddle (with pubsub faked) http://jsfiddle.net/canree/dD5VR/

I have external service (pubsub) and created angular service for it. Now as I don't want other parts of my app to be dependent on this concrete implementation , I decided to create another one (inbox) that would store all the messages pubsub sent. And this inbox would be the dependency across my app (instead of pubsub).

So I want my dependencies to be:

controller -> inbox -> pubsub

When pubsub receives a message it needs to add it to inbox so that controller can see it and react accordingly. The problem is I don't want this backward dependency (pubsub -> inbox). I'd like pubsub to notify observers that message was received.

What I have now is ugly callback registration (inbox registers callback in pubsub). I don't like it very much as it has a lot of boilerplate (regarding this handling etc).

I wonder if there is other way to connect those services? Events (but without being forced to use $rootScope everywhere)? If so, where to register such event handler? Can services receive events?

Take a look at the fiddle provided and advice me how to solve it better way.

4

1 回答 1

2

I don't want other parts of my app to be dependent on this concrete implementation

The interaction with the server is already wrapped/abstracted in the pubsub service. If the interaction with the server needs to change, it is already isolated to that service. I don't think adding another layer of abstraction buys you enough to offset the extra code you need to write (as you've already seen).

Here are a few other observations about how you could simplify your code (some of this you probably already know, but it might be instructive for others):

  1. The content() function is not necessary (especially since messages is not private data). In Angular the controller $scope/model is often directly tied to a service model, so you could simply use: $scope.messages = inbox.messages;
    (If you like the content() function, consider making messages private in the inbox service.)

  2. There is no need to send an event to the inbox controller about the change to inbox's messages array. The append() function just needs to call $rootScope.$digest(). And actually, this is probably not needed, since the real service would likely be using $http or $resource, which will automatically call $apply() or $digest. So _broadcastNewMessage() is not needed, nor is the $scope.$on() in the controller.
    Even if you leave the content() function as is, you still won't need to broadcast anything.

  3. Since inbox is dependent on pubsub, I would have the inbox service register itself pubsub.subscribe(this.append, this);

  4. pubsub's init() method can be in-line (no function required)

Fiddle with all of the above observations incorporated.

I wonder if there is other way to connect those services?

I can only think of model sharing (e.g., in service1: this.service1_obj_or_obj_property = service2.service2_obj_or_obj_property) and creating functions on the dependent service that the other service can call.

Can services receive events?

Since $on and $broadcast are defined on Scope, and since services are singletons and are not affected by scopes, I'm pretty sure the answer is "no."

于 2012-12-18T02:29:02.713 回答