- 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.
- 新編Visual Basic程序設計上機實驗教程
- Vue 3移動Web開發與性能調優實戰
- Practical Internet of Things Security
- AngularJS Web Application Development Blueprints
- Protocol-Oriented Programming with Swift
- C#程序設計教程(第3版)
- Instant Debian:Build a Web Server
- Mockito Essentials
- Python應用與實戰
- 少年小魚的魔法之旅:神奇的Python
- Python程序員面試算法寶典
- Learning C# by Developing Games with Unity 3D Beginner's Guide
- 邊做邊學深度強化學習:PyTorch程序設計實踐
- 瘋狂Java講義精粹
- Visual C++ 2017網絡編程實戰