2

Is there a less verbose way of accessing dependencies (i.e. constructor parameters) in prototype functions? Particularly for AngularJS Services.

I only know of

function SomeSrvc($http, ...other deps...) {
  var srvc = this;

  // Verbose way of storing dependencies
  srvc.$http = $http;
  srvc.dep2 = dep2;
  srvc.dep3 = dep3;
  srvc.dep4 = dep4;
}

SomeSrvc.prototype.doSomething = function() {
  var srvc = this;
  // Do stuff with srvc.$http and other srvc.deps...
};
4
  • 1
    This is how I've been doing it. I think that it might be one reason why JS people tend not to use the object's prototype all that frequently ... But I've always liked it even if it is slightly more verbose. Commented Mar 25, 2016 at 16:15
  • You could just inject $injector. Commented Mar 25, 2016 at 16:18
  • @elclanrs Can you show me the above example using $injector? Does it change the verbose way of passing to prototype functions? Commented Mar 25, 2016 at 16:26
  • You'd do function SomeSrvc($injector) then srvc.$http = $injector.get('$http'), so you still have to assign it Commented Mar 25, 2016 at 16:28

3 Answers 3

1

The shortest I know would be avoiding using prototype in an outer scope and simply use closures:

function SomeSrvc($http, ...other deps...) {
  var srvc = this;

  srvc.doSomething = function() {
    // just use $http without this / srvc
  };
}

Short and nice. If you really like prototype-like syntax, just adjust the indentation (but in my opinion this would be uglier):

function SomeSrvc($http, ...other deps...) {
  var srvc = this;



srvc.doSomething = function() {
  // Do stuff with srvc.$http and other srvc.deps...
};

}

This gives you the same effect - the object created with a new operator will have this function and angular services are created this way.

Additionally, this way has a really good side-effect. It does not create the variables on the service object, so they can be considered private, when assigning all your variables to the service makes them public and could be accessed from another angular module. Currently by just injecting your service you are able to use all injected modules by just calling e.g.

SomeSrvc.$http

which is totally against the whole idea of dependency injection.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, this certainly answers the question for less verbose. I thought about using it previously, but I didn't want to lose prototypical inheritance.
@lebolo Why do you need a prototypical inheritance? The angular services are singletons, they are created once with a new operator. You cannot reuse constructor function elsewhere, so prototype is just obsolete. In my opinion at least...
I've used it before (this shows an example in the module.service section).
yes, but in this example there are two "classes" which is slightly going against the angular way which instead of inheritance offers dependency injection for model and directives for views. And even with the method I proposed above you can still do inheritance by first creating object with a new SomeSrvc() and taking it's prototype. Just one step more
1

This is actually an official way described in documentation

function SomeClass(greeter) {
  this.greeter = greeter;
}

SomeClass.prototype.doSomething = function(name) {
  this.greeter.greet(name);
}

But I would consider to use ES2015 classes syntax instead.

export default class SomeClass {
  constructor(greeter) {
    this._greeter = greeter;
  }

  doSomething() {
    this._greeter.greet(name);
  }
}

You can read about it more here

8 Comments

Thanks, missed that part in the documentation!
how is this less verbose?
@smnbbrv It's not, but it's useful to know that this is the "official" way to do it in AngularJS. Makes me feel less like a chump =P
@lebolo angular guys still use $scope-variables-way instead of this way on the most pages of their documentation, but it does not mean it is a right way to go...
Personally I use ES2015, It's especially handy when you need extend a class
|
0

for services, not controllers, I've been doing something a little different

module.factory('myService', function(dep1, dep2){
    var createInternal=function(){ 
        var internal = Object.create(proto);
        internal.init( ... ); 
        return internal;
    };
    var service = function(){ 
        var internal = createInternal(); 
        return { 
            doSomething: function(a, b, c){ return internal.doSomething(a,b,c); },
            ...
        };
    };
    var proto = { 
        init: function( ... ){ 
                  dep1.greet();
                  dep2.doSomethingElse(); 
                  ... 
              },
        doSomething: function(a, b, c){ 
                  dep1.grito(b);
                  dep2.haceOtraCosa();
              },
        ...
    };
    return service();
});

It's a little bit different, but it breaks it up into a header and a list of prototype functions, which I like.

5 Comments

doesn't look like less verbose at all... Looks like spaghetti to me; to create one empty function on a service you use at least 20 lines of code...
to me, I'm either interested in what the service does, or what the prototype functions do, and so yeah, there's a lot of boilerplate, but the interesting parts of the code are easier to read because of it.
you could at least put some of these functions in a special service and reuse them everywhere. I really believe one can take half of these things in some external function which will bootstrap your service automatically in one line
it's not about memory, it's about total unreadability of your code
obviously we disagree

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.