0

I need an object to be globally accessible all throughout my Angular application, and I've gladly put this object in a value service.
Unfortunately, this object is computed by another service, and I've not been able to inject myService into same value service.

ATM, I've acheived my goal with something like this:

global service code

app.service('myService', function() {
    this.foo = function() {
        // some code that returns an object
        return computedObject
    }
})

app.run(function ($rootScope, myService) {
    $rootScope.global = {dbObject: myService.foo()}
})

And which I can use in any controller that pleases me by simply injecting $rootScope in it

However, I don't like the need of injecting the whole $rootScope wherever I need that damn object, and I trust is not much safe (or efficient?) either, since the team specifies

Of course, global state sucks and you should use $rootScope sparingly, like you would (hopefully) use with global variables in any language. In particular, don't use it for code, only data. If you're tempted to put a function on $rootScope, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested.

Conversely, don't create a service whose only purpose in life is to store and return bits of data.



Do you, perchance, happens to know any way I can inject a service into a service value?

Or maybe any other Angular best practice which I could exploit?


I forgot one very important notice

The computation of the object could be quite computational intense, so I absolutely don't want it to be recomputed everytime I move from page to page, or anything else really.

domokun
  • 3,013
  • 3
  • 29
  • 55
  • Can you show in example about: `Unfortunately, this object is computed by another service, and I've not been able to inject myService into same value service.` – Maxim Shoustin Oct 24 '13 at 12:39
  • Why can you not cache the `computedObject` in your `myService` and expose the value using the method `foo` as you have done. Whoever wants data can call the method `foo`. – Chandermani Oct 24 '13 at 12:43
  • @MaximShoustin I've wrote it in the code. In the first part I compute the object and in the second part I store it in the `$rootScope` I would have done something like this (made up syntax, ofc) `app.value( [myService], 'dbObject', myService.foo() )` – domokun Oct 24 '13 at 12:45
  • Its not good idea to use `rootScope` even if it's easy. I changed answser and added some code – Maxim Shoustin Oct 24 '13 at 12:51
  • Downvoted for what??? Is my question answered elsewhere? – domokun Oct 24 '13 at 13:04
  • Agreed - whoever downvoted should explain. Upvoted to compensate as it's a decent question. – Ed_ Oct 24 '13 at 16:22

3 Answers3

0

I need an object to be globally accessible all throughout my Angular application

I would use service. Since Service is singleton you can register the service to all your controllers and share any data over service.

Unfortunately, this object is computed by another service, and I've not been able to inject myService into same value service.

Just create one main service (Parent) and child service that will inherit the parent. (like abstract service in Java world).

Application.factory('AbstractObject', [function () {
   var AbstractObject = Class.extend({
        virtualMethod: function() {
           alert("Hello world");
        },
        abstractMethod: function() { // You may omit abstract definitions, but they make your interface more readable
           throw new Error("Pure abstract call");
        }
    });

    return AbstractObject; // You return class definition instead of it's instance
}]);

Application.factory('DerivedObject', ['AbstractObject', function (AbstractObject) {
    var DerivedObject = AbstractObject.extend({
        virtualMethod: function() { // Shows two alerts: `Hey!` and `Hello world`
            alert("Hey!");
            this._super();
        },
        abstractMethod: function() {
            alert("Now I'm not abstract");
        }
    });
    return DerivedObject;
}]);

Now, we can add some logic into AbstractObject and continue use DerivedObject Here is example Plunker

Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • Did you literally read the first half of the first sentence then stop? Edit: I need an object to be globally accessible all throughout my Angular application, and **I've gladly put this object in a value service.** – Ed_ Oct 24 '13 at 12:35
  • 1st off i did read all question. Second - i didnt finish. 3d, its not so good to use `rootScope` (sure u can) – Maxim Shoustin Oct 24 '13 at 12:38
  • @EdHinchliffe and what after? I try to convince him to use service but not root scope. Downvote means: my answer is wrong, and please, explain why my answer is wrong. Thanks – Maxim Shoustin Oct 24 '13 at 12:54
  • Downvote doesn't mean your answer is wrong. It means it isn't useful. The first sentence of the question stated that the asker was using a service. Your answer at the time contained only "use a service", with a quote for half of the first sentence. You have now modified your answer enough that it is useful again, hence I've removed your downvote. Try not submitting an answer until it's complete, or at least complete enough to be useful. – Ed_ Oct 24 '13 at 13:55
0

Ideally Using $rootScope for storing a few globally required values is totally ok. But if you are still adamant on using a module, I suggest you use a provider. Make your 'myService' a provider and that will let you configure the variables in the service.

More info here AngularJS: Service vs provider vs factory

Community
  • 1
  • 1
djd
  • 1,007
  • 1
  • 7
  • 20
  • I guess a `factory` could suite my well enough, but I wonder, can you tell me what's the advantage on injecting the `$rootScope` ? – domokun Oct 25 '13 at 08:32
0

You could use $broadcast to send the value from the value service to myService.

You would still need to inject $rootscope into each of the services, but from then on you could just inject myService around the rest of the app.

Reference here.

Ed_
  • 18,798
  • 8
  • 45
  • 71
  • Actually the value already is in `myService`, or at least the function which computes it. It's the other way around I need – domokun Oct 24 '13 at 12:51
  • I don't get why you can't just store the computed value on the service itself? I.e. `this.bar = this.foo();` then just use `myService.bar`? – Ed_ Oct 24 '13 at 13:58
  • There's no reason I can't, but i have two question: 1) I may need the value **before** the service is injected in the controller. Can I still have it? 2) Does the value get recomputed every time I call a controller or, since the service is a singleton, it gets computed only once? – domokun Oct 24 '13 at 15:59
  • 1) you wouldn't be able to access it from the controller until you inject it, but you can of course access it from wherever else you can access the singleton. 2) The value would only get computed when you call the `foo` method. It will get called once when the service is initially created (i.e. the `this.bar=this.foo()` code), but that will only happen once (singleton). – Ed_ Oct 24 '13 at 16:21