angularJS 系列(三)- 自定義 Service

參考:http://viralpatel.net/blogs/angularjs-service-factory-tutorial/javascript

https://www.pluralsight.com/blog/tutorials/angularjs-step-by-step-servicesjava

想法:定義一個 angular module 以後呢, 在許多的 controller 中會有一些公共的函數,或者是說在不少controller 中都要使用到的共同的方法,相似的邏輯實際上是能夠提取出來,進行封裝。angularjs

這樣,就抽象出來了 service 這樣一個概念。ajax

來繼續深刻理解一下,app

一、到底什麼是 service 呢?(what is a service ?)less

抽象出來的service 是無狀態的,將一些種類的方法封裝成一個對象。函數

The type of service I'm talking about is typically stateless and encapsulates some sort of functionality。post

二、爲何須要 service 呢?(why we need services ?)fetch

In my previous post about AngularJS controllers, I spoke a bit about the need for separation of concerns in modern-day JavaScript applications, which are much more involved than those of a decade ago. With the amount of JavaScript needed in a modern-day application, the architecture of your JavaScript takes on much more importance. Two of the five SOLID principles of object oriented design are directly related to Services: the Single Responsibility Principle (SRP) and the Dependency Inversion Principle (DIP).ui

The single responsibility principle teaches that every object should have a single responsibility. If we use the example of a controller, it's responsibility is essentially to wire up the scope (which holds your models) to your view; it is essentially the bridge between your models and your views. If your controller is also responsible for making ajax calls to fetch and update data, this is a violation of the SRP principle. Logic like that (and other business logic) should instead be abstracted out into a separate service, then injected into the objects that need to use it.

This is where the Dependency Inversion Principle comes in. The DIP states that objects should depend on abstractions, not concretions. In languages like C# and Java, this means your objects depend on Interfaces instead of Classes. In JavaScript you could look at any parameter of any function (constructor function or otherwise) as an abstraction, since you can pass in any object for that parameter so long as it has the members on it that are used within that method. But the key here is the ability to use dependency injection - the ability to inject into other objects. This means that all of your controllers, directives, filters and other services should take in any external dependencies as parameters during construction. This allows you to have loosely coupled code and has the added benefit of making unit testing much easier.

 

 

Use  if object definition syntax is preferable
factory
app.factory('factory', function () {
    ...
    return {
        value: '...'
    };
});

  

or it returns something that is not an object for some reason.

Use service if this syntax is preferable

app.service('service', function () {
    this.value = '...';
});

  or it should return an object created with new from another constructor, e.g.

app.factory('factory', function () {
    return new someConstructor();
});

  VS

app.service('service', someConstructor);

  A good use case for service is that you can seamlessly refactor existing controllers with controllerAs syntax to inherit from common service, in this case no this statements replacement is required, as shown here:

app.service('parentControllerService', function () {
    this.value = '...';
});

app.controller('MainController', function (parentControllerService) {
    angular.extend(this, parentControllerService);
});

app.controller('ChildController', function (parentControllerService) {
    angular.extend(this, parentControllerService);
    this.value = '!!!';
});
相關文章
相關標籤/搜索