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

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.

主站蜘蛛池模板: 本溪| 广西| 宁国市| 东山县| 宜良县| 建湖县| 新乡市| 确山县| 宜兰市| 太仓市| 教育| 开江县| 海兴县| 和顺县| 洪湖市| 普兰店市| 云龙县| 皮山县| 富裕县| 宜昌市| 新安县| 叙永县| 民和| 巴林左旗| 宁国市| 广水市| 九江市| 鄱阳县| 江山市| 奎屯市| 杭州市| 台中县| 阳山县| 桐乡市| 班戈县| 咸丰县| 松阳县| 襄汾县| 南郑县| 盐城市| 桦南县|