zoukankan      html  css  js  c++  java
  • AngularJS 服务简介

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

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

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


    Service

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


    先从注册一个服务开始,注册服务的最常见方式便是factory()
    比如:

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


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

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

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

    好了,先把myService修改一下:

    .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};
        });
    })
  • 相关阅读:
    .net core 部署到 iis 步骤及报错解决方法
    数据库学习笔记3 基本的查询流 2
    数据库学习笔记 2 数据库文件基本查询
    我对于C#的想法
    数据库学习笔记 一
    openwrt 软件安装依赖冲突
    openwrt 自定义DHCP
    asp.net core 3.1 入口:Program.cs中的Main函数
    c# 匿名方法(函数) 匿名委托 内置泛型委托 lamada
    家庭网络那些事
  • 原文地址:https://www.cnblogs.com/jinkora/p/4306059.html
Copyright © 2011-2022 走看看