AngularJS Services

How do we share data between controllers? 

$scope ?

Requires Nesting

 

Introduces Tight Coupling

 

Hard to test

Events?

$broadcast, $emit, $on

 

https://github.com/angular/angular.js/wiki/Best-Practices

Event Soup

 

Introduces Tight Coupling

 

Hard to test

Services?

Services...

  • Share business logic 
  • Lazily Instantiated
  • Singleton Objects
  • $http, $rootScope...
var exampleService = function(){
    var _foo = "bar";
    this.getFoo = function(){
        return _foo;
    }
});

app.service('exampleService', exampleService)
class exampleService
    @foo = "Bar"
    getFoo: -> 
        @foo
   
app.service 'exampleService', exampleService

Service = Singleton

app.controller "exampleCtrl",
    ($scope, exampleService) ->
        $scope.foo = exampleService.foo
class sharedStateService
    @foo = "Foo"

app.services "sharedStateService", sharedStateService

Sharing State

app.controller 'firstController', ($scope, sharedStateService) ->
    $scope.foo = sharedStateService.foo
        
    $scope.watch('sharedStateService.foo', 
        (newVal, oldVal, scope) -> 
            if (newVal != oldVal)
                scope.foo = newVal

X2

Interacting with external API's

class httpWrapperService
    @inject: ['$http']
    $http = null
    constructor: ($http) ->
        $http = $http
    
    getAll: -> 
        promise = $http.get('url/of/resource')

        return promise
        
app.service 'httpWrapperService', httpWrapperService

Interacting with external API's

api.controller 'httpGetController',
    ($scope, httpWrapperService) ->
    
        # Call .getAll() on controller 
        # initialization
        
        httpWrapperService.getAll().then (response) ->
            $scope.all = response.body

State + External API's

class httpStateService

    @inject: ['$http']
    $http = null

    constructor: ($http) ->
        $http = $http
        @observerCallbacks = []
    
    getAll: -> 
        promise = $http.get('url/of/resource')
        promise.then (response) =>
            @all = all
            @notifyCallbacks()
        return promise
        
    registerCallback: (callback)
        @observerCallbacks.push callback
 
    notifyCallbacks: ->
        angular.forEach @observerCallbacks, (callback) ->
            callback()

app.service 'httpWrapperService', httpWrapperService

State + External API's

api.controller 'httpGetController',
    ($scope, httpStateService) ->
   
        updateAll = -> 
            $scope.all = httpStateService.all
        httpStateService.registerCallback updateAll
        httpStateService.getAll()

Services!

...Factories?

A Factory returns a reference to the function. 

A Service returns a single instance of that function

class factoryExample
    constructor: (@foo) ->

app.factory 'factoryExample', factoryExample


class serviceExample
    @foo = "Bar"

app.service 'serviceExample', serviceExample


app.controller 'exampleController', 
    ($scope, serviceExample, factoryExample) -> 
        
        # you create new factories...
        fooCreator = new factoryExample("Baz")
        $scope.localFoo = fooCreator.foo


        # ... and you refer to a single service.
        $scope.sourceOfAllTruth = serviceExample.foo
class factoryServiceExample
    constructor: (@foo) ->

newService = new factoryServiceExample("bar")

app.factory 'factoryExample', newService

Why Services?

Encapsulates business logic

 

Provides clean interface to external API's 
 

Shares state between related controllers

...and they're Testable

http://nathanleclaire.com/blog/2014/04/12/unit-testing-services-in-angularjs-for-fun-and-for-profit/

https://docs.angularjs.org/guide/services


http://stackoverflow.com/questions/15666048/service-vs-provider-vs-factory

http://nathanleclaire.com/blog/2014/04/12/unit-testing-services-in-angularjs-for-fun-and-for-profit/


Additional Reading: 

 

AngularJS Services

By Alex Jarvis

AngularJS Services

How do we share information between controllers in AngularJS?

  • 931