- Switching to Angular(Third Edition)
- Minko Gechev
- 705字
- 2021-07-02 15:23:34
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.
- 數據庫系統原理及MySQL應用教程(第2版)
- 基于粒計算模型的圖像處理
- Getting Started with Gulp(Second Edition)
- Linux核心技術從小白到大牛
- PaaS程序設計
- AIRAndroid應用開發實戰
- jQuery從入門到精通 (軟件開發視頻大講堂)
- Linux網絡程序設計:基于龍芯平臺
- Windows Server 2016 Automation with PowerShell Cookbook(Second Edition)
- 零基礎入門學習Python
- 移動界面(Web/App)Photoshop UI設計十全大補
- PyQt編程快速上手
- Photoshop智能手機APP界面設計
- 高性能PHP 7
- Java服務端研發知識圖譜