Skip to content

Instantly share code, notes, and snippets.

@joelhooks
Last active December 21, 2015 04:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joelhooks/6251511 to your computer and use it in GitHub Desktop.
Save joelhooks/6251511 to your computer and use it in GitHub Desktop.
Short example of how to declare services in AngularJS.
//from most to least verbose, but it is all the same in the end.
(function() {
var module = angular.module("myApp.myModel", []);
var MyModel = function MyModel() {
this.asyncService = null;
this.someApi = function() {
return this.asyncService.getStuff(); //promise?
}
}
var myModelProvider = Class.extend({
model: new MyModel();
$get: ['asyncService', function (asyncService) {
model.asyncService = asyncService; //dependency injection
return model; //resolved for the lifetime of app
}]
});
modules.provider('myModel', myModelProvider);
}())
// or
(function() {
var module = angular.module("myApp.myModel", []);
var MyModel = function MyModel(asyncService) {
this.asyncService = null;
this.someApi = function() {
return this.asyncService.getStuff(); //promise?
}
}
module.factory('myModel', ['asyncService', function (asyncService) {
//could do some stuff here
return new MyModel(asyncService);
}]);
}())
// or
(function() {
var module = angular.module("myApp.myModel", []);
var MyModel = function MyModel(asyncService) {
this.asyncService = null;
this.someApi = function() {
return this.asyncService.getStuff(); //promise?
}
}
module.service('myModel', ['$asyncService', MyModel]); //most simple option
}())
@netpoetica
Copy link

Where are you getting Class.extend from? Maybe you mean Angular.extend? Or you're using Simple Inheritance by Resig?

@ThomasBurleson
Copy link

The above code appears to be wrong. Here are some proposed fixes:

var MyModel = function (asyncService) {
        this.asyncService = asyncService;

        this.someApi = function() {
            return this.asyncService.getStuff(); //promise?
        }

    }

Also here are some additional feedback items:

  1. You are not using the module pattern properly
  2. Your approach requires angular.service() be used and fails if angular.factory() is used by mistake. Since .service() calls use the new operator this is scoped for the new instance. .factory(), however, does not use the new operator so this will not be valid.

Here is a solution that solves all of the above issues:

(function(angular) {
    "use strict";

        /**
         * MyModel constructor function
         */
    var MyModel = function ($asyncService) {

        // publish API for MyModel
        return {
            asyncService : $asyncService,
            someApi      : function() {
                return $asyncService.getStuff();
            }
        };
    };

    // Redefine for minification...
    MyModel = [ '$asyncService', MyModel ];


    // Register `myModel` as an instance of the MyModel service or factory.
    angular.module( "myApp.myModel", [])
           .service('myModel', MyModel); 

}(angular));

@netpoetica
Copy link

I was able to get a working version of this without all of the abstraction, but I had to do something kind of hacky and ad a run() function to my main angular app declaration. It isn't evil, but it is strange. Mostly because I don't have to actually DO anything in that run function, just using it to tell Angular to load my core data Model at run time (simply by declaring it as a dependency of run) so it will be ready when I run dependant routes/controllers later

@ThomasBurleson
Copy link

@netpoetica -

$asyncService is another instance (of a Class, object, function) that was

  1. registered with Angular (via .service() or .factory(), and then later...
  2. instantiated by the Angular engine during the app bootstrapping processes
// register AsyncService to create instance of $asyncService
angular.module( "myApp.myModel", [ ])
          .service( "$asyncService", AsyncService)
          .service('myModel', MyModel);

This instance $asyncService is then injected as an parameter to the function MyModel( ) invocation; which creates an instance of myModel.

See how Angular allows you to create beans/services, define dependencies, and auto-injects those as needed?

@ThomasBurleson
Copy link

@netpoetica -

angular.run() tells the NG engine to start

  1. Processing the html to determine which Angular construction is needed
  2. Instantiating all the required, registered services, values, and factories.

It uses ng-app, ng-controller etc in the HTML to determine what to load/instantiate at what time.

@joelhooks
Copy link
Author

Thanks @ThomasBurleson. These were thrown together as a quick example for somebody and I never actually ran them (or even studied them more than a moment). Munged together from three code bases on my hard drive with names change to protect the innocent :>

@netpoetica Class is John Resig's simple class inheritance. http://ejohn.org/blog/simple-javascript-inheritance/

@ThomasBurleson
Copy link

@joelhooks
Just working for you as a second pair of eyes ;-).

BTW, rumour/documentation implies that a factory creates a singleton. Since a service (which uses new) does not necessarily create a singleton, here is a way to easy force/manage singletons regardless of .factory() or .service() instantiations.

(function(angular) {
    "use strict";

    var _service    = null,
          _singleton = {
            asyncService : function() { return _service              },
            someApi      : function() { return _service.getStuff();  }
        };

        /**
         * MyModel constructor function
         */
        MyModel = function ($asyncService) {
            _service =  $asyncService || _service;
            return _singleton;
        };
    },


    // Redefine for minification...
    MyModel = [ '$asyncService', MyModel ];


    // Register `myModel` as an instance of the MyModel service or factory.
    angular.module( "myApp.myModel", [])
           .service('myModel', MyModel); 

}(angular));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment