AngularJS - 服务简介

服务是AngularJS中很是重要的一个概念,虽然咱们有了控制器,但考虑到其生命实在脆弱,咱们须要用到服务。git

起初用service时,我便把servicefactory()理所固然地关联起来了。
确实,factory()是建立一个服务的最简单的方式,但服务并不是仅此而已。github

这里记录一下我对服务的一些简单认识。


api

Service

很是重要的一点 —— 服务是单例
一个服务在一个AngularJS应用中只会被$injector实例化一次,并贯穿应用的整个生命周期,与脆弱的控制器们进行通讯。ide


先从注册一个服务开始,注册服务的最多见方式即是factory()
好比:函数

var myApp = angular.module('myApp',[])
.factory('myService',function() {
    return {};
});


factory()以对象或者函数形式返回一个服务。
咱们试试给myService注入$http服务,写一个像那么回事的东西。this

(ps:找了一些URL都不是很理想,我也只好学别人的demo,从github获取用户的活动日志信息)url

注入? 把服务注入给控制器也是这样,把服务的名字放到参数列表里就算是注入了,但这只是简单的方式。日志

好了,先把myService修改一下:code

.factory('myService',function($http) {

    return {
        getUserActivities: function(username){
            return $http({
                method: 'JSONP',
                url:'https://api.github.com/users/'+username+'/events?callback=JSON_CALLBACK'
            });
        }
    };
})

 

根据输入的用户名进行请求,输出活动信息,视图以下:对象

<div ng-controller="myController">
    <input type="text" ng-model="username" />
    <table border="1">
        <tr>
            <th></th>
            <th>user</th>
            <th>to</th>
            <th>at</th>
        </tr>
        <tr ng-repeat="activity in activities">
            <td><img src="{{activity.actor.avatar_url}}" width="25px" height="25px"/></td>
            <td>{{ activity.actor.login }} </td>
            <td>{{ activity.repo.name }}</td>
            <td>{{activity.created_at}}</td>
        </tr>
    </table>
</div>


咱们须要$watch这个变量,但须要注意的是,若是请求频率超过限制,github会给个403。
所以还须要用$timeout控制一下请求频率,一段时间以内重复请求就把以前的干掉。
控制器调用服务代码以下:

.controller('myController',function($scope,myService,$timeout,$log){

    var timeout;
    $scope.$watch('username',function(){
        if(timeout){
            $timeout.cancel(timeout)
            $log.info('timeout:::'+timeout);
        }               

        timeout= $timeout(function(){
            myService.getUserActivities($scope.username)
            .success(function(response, status, headers, config){
                $scope.activities = response.data;
            })
            .error(function(response, status, headers, config){
                $log.info(status)
            })},1000);
    });
})


factory()注册一个服务彷佛不那么复杂。
事实上,咱们有5种方式来建立服务:

  • factory
  • service
  • constant
  • value
  • provider

factory

最简单的方式,该函数接收2个参数

  • name (string):服务名
  • getFn (function/array):AngularJS实例化服务时调用该函数

service

多是由于更加语义化的缘故,比起factory(),我更喜欢service()
service也一样接收2个参数,分别是:

  • name (string):服务名
  • constructor (function):服务对象的构造函数

试着改用service():

.service('myService',function($http) {
    this.getUserActivities = function(username){
        return $http({
            method: 'JSONP',
            url:'https://api.github.com/users/'+username+'/events?callback=JSON_CALLBACK'
        });
    }
})

constant与value

这两个名字感受比较另类,它们的参数都是同样的:

  • name
  • value

仅从语义上来说,若是服务的$get方法只是返回个常量,这两个方法确实适合。
可能会尝试写个函数进去,若是只是定义的话则不会报错。
但不会有相应的provider,调用时也会提示该服务不是一个函数之类的问题。

因此仍是老老实实地这样使用:

.constant('serviceId','00001')


那二者的区别又是什么?
区别在于注入到config()时,以上面的serviceId为例。
若是serviceId是个constant,咱们能够将serviceId注入到config()中,可是没法将serviceIdProvider注入到config()中,而value则恰好相反。

provider

provider()是最原始的方法。
咱们试着用factory()provider()建立相同的服务进行对比。

.factory('aService',{
    'name':'a'
})
.provider('bService',{
    $get: {'name':'b'}
})


也就是说factory()的第二个参数至关因而$get?
provider()接收两个参数:

  • name (string) :仍然是服务实例的名字,若是name+'Provider'即是provider的名字。
  • provider (object/array/function) : 不是服务,是带$get()的provider

$provide服务在运行时初始化provider,$injector调用$get建立服务实例。
那为何要用provider()而不是其余方式? 关键在于config(),若是咱们给多个应用共享某个服务,但在注入服务以前给注入到不一样应用的服务进行相应的设置,则须要在config()中经过服务的provider进行设置,好比加个decorator什么的。

decorator

就是装饰服务,添加功能或者彻底改变服务。
decorator()接收两个参数

  • name (string):要装饰的服务的名称
  • decoratorFn (function):服务实例化时由$injector调用该函数。

下面是一个例子,在得到用户活动信息后输出耗时:

.config(function(myServiceProvider,$provide){
    $provide.decorator('myService',function($delegate,$log) {
        var activities = function(username) {
            var startedAt = new Date();
            var activities = $delegate.getUserActivities(username);
            activities.finally(function() {
                $log.info("Fetching activities" +" took " +(new Date() - startedAt) + "ms");
            });
            return activities;
        };
        return {getUserActivities:activities};
    });
})
相关文章
相关标签/搜索