官术网_书友最值得收藏!

Services

Services are the building blocks that Angular provides for the definition of the business logic of our applications. In AngularJS, we had three different ways of defining services:

// The Factory method 
module.factory('ServiceName', function (dep1, dep2, ...) { 
  return { 
    // public API 
  }; 
}); 
 
// The Service method 
module.service('ServiceName', function (dep1, dep2, ...) { 
  // public API 
  this.publicProp = val; 
}); 
 
// The Provider method 
module.provider('ServiceName', function () { 
  return { 
    $get: function (dep1, dep2, ...) { 
      return { 
        // public API 
      }; 
    } 
  }; 
}); 

Although the first two syntactical variations provide similar functionality, they differ in the way the registered service will be instantiated. The third syntax allows further configuration of the registered provider during configuration time.

Having three different methods for defining services is quite confusing for the AngularJS beginners. Let's think for a second what necessitated the introduction of these methods for registering services. Why can't we simply use JavaScript constructor functions, object literals, or ES2015 classes instead, which Angular will not be aware of? We can encapsulate our business logic inside a custom JavaScript constructor function like this:

function UserTransactions(id) { 
  this.userId = id; 
}
 
UserTransactions.prototype.makeTransaction = function (amount) { 
  // method logic 
}; 
 
module.controller('MainCtrl', function () { 
  this.submitClick = function () { 
    new UserTransactions(this.userId).makeTransaction(this.amount); 
  }; 
}); 

This code is completely valid. However, it doesn't take advantage of one of the key features that AngularJS provides: the DI mechanism. The MainCtrl function uses the UserTransaction constructor function, which is visible in its body. The preceding code has two main pitfalls:

  • We're coupled with the logic used for the service's instantiation.
  • The code is not testable. In order to mock UserTransactions, we need to monkey patch it.

How does AngularJS deal with these two things? When a given service is required, through the DI mechanism of the framework, AngularJS resolves all of its dependencies and instantiates it by passing it to a factory function, which encapsulates the logic for its creation. The factory function is passed as the second argument to the factory and service methods. The provider method allows the definition of a service on a lower level; for the factory method there is the one under the $get property.

Just like AngularJS, the new versions of Angular tolerates this separation of concerns as well, so the core team kept the services. In contrast to AngularJS, Angular provides a much simpler interface for their definition by allowing us to use plain ES2015 classes. We cannot escape from the fact that we need to explicitly state the services that should be available for injection and somehow specify instructions for their instantiation. In contrast to AngularJS, now the framework uses the ES2016 decorator's syntax and providers for this purpose, instead of the methods familiar to us from AngularJS. This allows us to define the services in our applications as simple as ES2015 classes, with decorators for configuration of the DI:

import {Injectable} from '@angular/core'; 
 
@Injectable() 
class HttpService { 
  constructor() { /* ... */ } 
} 
 
@Injectable() 
class User { 
  constructor(private service: HttpService) {}
 
  save() { 
    return this.service.post('/users') 
      .then(res => { 
        this.id = res.id; 
        return this; 
      }); 
  } 
} 

Services are related to the components and the directives described in the previous sections. For developing highly coherent and reusable UI components, we need to move all the business-related logic to inside our services. Also, in order to develop testable components, we need to take advantage of the DI mechanism to resolve all their dependencies.

Another key difference between the services in AngularJS and Angular is the way the frameworks represent them internally. AngularJS uses strings to identify the different services and the associated factories used for their instantiation. On the other hand, now Angular uses keys instead. Usually, keys are the types of the distinct services. Another core difference in the instantiation is the hierarchical structure of injectors, which encapsulate different dependency providers with different visibility.

One more distinction between the services in AngularJS and Angular is the simplified syntax. The DI in Angular has a completely different syntax and has improved behavior by providing a consistent way of injecting dependencies. You can also find a more detailed explanation of Angular services and DI in Chapter 6, Dependency Injection in Angular.

主站蜘蛛池模板: 彰化县| 河津市| 循化| 太原市| 郑州市| 固镇县| 永福县| 楚雄市| 聂荣县| 南木林县| 沾化县| 肃宁县| 宜兰市| 沙坪坝区| 望城县| 云安县| 济阳县| 汉沽区| 临高县| 章丘市| 台中市| 隆回县| 离岛区| 神农架林区| 民权县| 五家渠市| 罗田县| 五家渠市| 台安县| 宁明县| 沙河市| 卢湾区| 内江市| 南开区| 乌兰察布市| 青铜峡市| 新民市| 商丘市| 沙河市| 灵石县| 包头市|