{% raw %}

# AngularJS 服务（内置和自定义）

> 原文： [https://howtodoinjava.com/angularjs/angularjs-services-built-in-and-custom/](https://howtodoinjava.com/angularjs/angularjs-services-built-in-and-custom/)

正如我们在 [Angular 介绍](//howtodoinjava.com/angularjs/angularjs-tutorial-helloworld-example/)中了解到的，服务是**无状态对象和单例对象**，它们为 Web 应用提供功能。 例如，`$http`是用于对 Web 服务器进行 HTTP 调用的核心服务。 简单来说，您可以将 Angular 服务假定为可重用代码块，它执行一个或多个相关任务（例如 Java 中带有静态方法的工具类）。 在 AngularJS 中，有几个内置服务 – 您也可以创建自己的自定义服务。

```java
Table of Contents

Built-in Services
Creating Custom Services
How to use Services
```

## 内置 Angular 服务

如前所述，Angular 提供了几种内置服务，这些服务可以即时使用。 在运行时，这些服务会自动向依赖项注入器注册，因此您可以通过使用依赖项注入轻松地将它们合并到您的 angular 应用中。 例如，要在控制器中使用`$http`服务，请按以下步骤注入服务：

```java
module.controller('DemoController', function( $http ){
    //...
});
```

让我们列出有 Angular 的内置服务。

| 服务名称 | 描述 |
| --- | --- |
| `$anchorScroll` | 提供滚动到`$location.hash()`中指定的页面锚点的功能 |
| `$animate` | 该服务公开了一系列 DOM 工具方法，这些方法提供对动画挂钩的支持。 |
| `$animateCss` | 默认情况下，仅当包含`ngAnimate`时，此服务才会执行动画。 |
| `$cacheFactory` | 构造缓存对象，放置和检索键值对并为其提供对其他服务的访问权限的工厂。 |
| `$templateCache` | 首次使用模板时，会将其加载到模板缓存中以便快速检索。 |
| `$compile` | 将 HTML 字符串或 DOM 编译到模板中，并生成模板函数，然后可以使用该函数将范围和模板链接在一起。 |
| `$controller` | 这负责实例化 Angular 控制器组件。 |
| `$document` | 指定对`window.document`元素的 [jQuery 包的](//howtodoinjava.com/scripting/jquery/javascript-dom-objects-vs-jquery-objects/)引用。 |
| `$exceptionHandler` | Angular 表达式中任何未捕获的异常都委托给此服务。 默认实现只是委派给`$log.error`，它将其记录到浏览器控制台中。 |
| `$filter` | 过滤器用于格式化显示给用户的数据。 |
| `$httpParamSerializer` | 默认的`$http`参数序列化程序，将对象转换为字符串。 |
| `$httpParamSerializerJQLike` | 替代`$http`参数序列化器，它遵循 jQuery 的`param()`方法逻辑。 序列化程序还将按字母顺序对参数进行排序。 |
| `$http` | 此服务有助于通过浏览器的`XMLHttpRequest`对象或`JSONP`与远程 HTTP 服务器进行通信。 |
| `$xhrFactory` | 用于创建`XMLHttpRequest`对象的工厂函数。 |
| `$httpBackend` | 用于处理浏览器不兼容。 |
| `$interpolate` | 将带有标记的字符串编译为插值函数。 HTML `$compile`服务使用此服务进行数据绑定。 |
| `$interval` | Angular 的`window.setInterval`包装器。 |
| `$locale` | 提供各种 Angular 组件的本地化规则。 |
| `$location` | 它解析浏览器地址栏中的 URL，并使该 URL 可用于您的应用。 对地址栏中 URL 的更改将反映到`$location`服务中，对`$location`的更改将反映到浏览器地址栏中。 |
| `$log` | 控制台日志。 |
| `$parse` | 将 Angular 表达式转换为函数。 |
| `$q` | 帮助您异步运行函数，并在完成处理后使用它们的返回值（或错误）。 |
| `$rootElement` | Angular 应用的根元素。 |
| `$rootScope` | 范围提供了模型和视图之间的分离。 这是针对根范围的。 每个应用都有一个根范围。 |
| `$sceDelegate` | 由后端`$sce`使用。 |
| `$sce` | 为 AngularJS 提供严格的上下文转义服务。 |
| `$templateRequest` | 它运行安全检查，然后使用`$http`下载提供的模板，并在成功后将内容存储在`$templateCache`中。 |
| `$timeout` | Angular 的`window.setTimeout()`包装器 |
| `$window` | 对浏览器的`window`对象的引用。 尽管`window`在 JavaScript 中全局可用，但由于它是全局变量，因此会引起可测试性问题。 在 Angular 上，我们始终通过`$window`服务来引用它，因此可以对其进行覆盖，删除或模拟以进行测试。 |

*参考： [https://docs.angularjs.org/api/ng/service](https://docs.angularjs.org/api/ng/service)*

## 创建自定义 Angular 服务

将应用的业务逻辑和通用操作放在一个地方总是一个好的设计。 这样可以提高代码的可重用性，并避免代码重复。 您应将所有此类逻辑放入自定义 Angular 服务中。 这使代码模块化并且更易于维护。

此外，您的代码变得更具可测试性。 请记住，Angular 为单元测试提供了一流的支持。 因此，我们可以为这些服务快速编写测试，并避免许多可能的缺陷。

声明 angularjs 服务的方式主要有两种。 让我们了解两种方式：

#### 使用`module.service('serviceName', function(){})`

当您使用`module.service()`和**创建服务时**，作为第二个参数传递的`function()`的实例成为 AngularJS 注册并随后在需要时注入到其他服务/控制器的服务对象。

使用`module.service()`在自定义服务对象中声明方法的语法为：

```java
module.service('DemoService', function() {
	//"this" will be used as service instance
    this.firstMethod = function() {
        //..
    }

    this.someOtherMethod = function() {
        //..
    }
});
```

#### 使用`module.factory('factoryName', function(){})`

当您使用`module.factory()`创建服务时，作为第二个参数传递的`function()`的**返回值**将成为 AngularJS 注册并稍后在需要时注入到其他服务/控制器的服务对象。

使用`module.factory()`在自定义服务对象中声明方法的语法为：

```java
module.factory('DemoService', function() {
	//"factory" will be used as service instance
	var factory = {}; 

    factory.firstMethod = function() {
        //..
    }

    factory.someOtherMethod = function() {
        //..
    }

    return factory;
});
```

## 如何使用 AngularJS 服务

此示例演示了自定义服务的用法，该服务具有用于显示不同时区的当前时间的逻辑。 首先创建自定义服务。

```java
var app = angular.module('myApp', []);

//Create a function
function TimeObj() {
    var cities = {
        'Los Angeles': -8,
        'New York': -5,
        'London': 0
    };
    this.getTZDate = function(city) {
        var localDate = new Date();
        var utcTime = localDate.getTime() + localDate.getTimezoneOffset() * 60 * 1000;
        return new Date(utcTime + (60 * 60 * 1000 * cities[city]));
    };
    this.getCities = function() {
        var cList = [];
        for (var key in cities) {
            cList.push(key);
        }
        return cList;
    };
}

//Register as service 'TimeService'
app.service('TimeService', [TimeObj]);

```

现在要使用此服务，请使用如下控制器：

```java
app.controller('LAController', ['$scope', 'TimeService',
    function($scope, timeS) {
        $scope.myTime = timeS.getTZDate("Los Angeles").toLocaleTimeString();
    }
]);

app.controller('NYController', ['$scope', 'TimeService',
    function($scope, timeS) {
        $scope.myTime = timeS.getTZDate("New York").toLocaleTimeString();
    }
]);

app.controller('LondonController', ['$scope', 'TimeService',
    function($scope, timeS) {
        $scope.myTime = timeS.getTZDate("London").toLocaleTimeString();
    }
]);

```

现在，您可以在网页中使用控制器显示不同的时间。

```java
<html ng-app="myApp">
	<head>
		<title>AngularJS Custom Time Service</title>
		<style>
			span {
				color: lightgreen; background-color: black;
				border: 3px ridge; padding: 2px;
				font: 14px/18px arial, serif; 
			}
		</style>
	</head>
	<body>
		<h2>Custom Time Service:</h2><hr>

		<div ng-controller="LAController">
		Los Angeles Time:
		<span>{{myTime}}</span>
		</div><hr>

		<div ng-controller="NYController">
		New York Time:
		<span>{{myTime}}</span>
		</div><hr>

		<div ng-controller="LondonController">
		London Time:
		<span>{{myTime}}</span>
		</div>

	</body>
</html>
```

输出将如下所示：

请参阅 [CodePen](https://codepen.io) 上的 [Angular 服务演示 – 时区示例](https://codepen.io/howtodoinjava/pen/jWxYKB/)，作者为 Lokesh（[@howtodoinjava](https://codepen.io/howtodoinjava)）。

这就是 **AngularJS 服务入门教程**的全部内容。 将我的问题放在评论部分。

学习愉快！

{% endraw %}