angularJS的services讲解
2017-02-22 23:37

此文是翻译文章,翻译自angularJS的service服务介绍

services服务

angularJS的services是一些可以替代的对象,通过依赖注入的方式结合在一起。你可以在app应用中通过使用services服务组织和分享代码。达到功能的共享。

angularJS的services是:

@1:延迟实例化--只有在应用组件依赖一个服务时,angularJS才会实例化它。

@2:单例模式--每一个应用组件都是服务工厂创建的服务实例的一个引用。

angularJS提供了一些有用的服务(例如$http),但是在大部分app应用中,你仍然需要你自己的服务。

笔记:像其他核心angularJS标识符一样,内置服务通常以“$”开始(例如$http)。

使用一个services服务

给依赖某个service的组件(controller,services,filter或者directive)添加一个服务作为组件的依赖。angularJS的依赖注入子系统将会处理这个依赖。

<div id="simple" ng-controller="MyController">
  <p>创建一个notify服务,注入到controller中</p>
  <input ng-init="message='test'" ng-model="message" >
  <button ng-click="callNotify(message);">NOTIFY</button>
  <p>(you have to click 3 times to see an alert)</p>
</div>


angular.module('myServiceModule', []).
 controller('MyController', ['$scope', 'notify', function($scope, notify) {
   $scope.callNotify = function(msg) {
     notify(msg);
   };
 }])
 .factory('notify', ['$window', function(win) {
   var msgs = [];
   return function(msg) {
     msgs.push(msg);
     if (msgs.length === 3) {
       win.alert(msgs.join('\n'));
       msgs = [];
     }
   };
 }]);
it('should test service', function() {
  expect(element(by.id('simple'))
  .element(by.model('message'))
  .getAttribute('value'))
  .toEqual('test');
});

创建services服务

通过在angularJS的module上注册service的名字和service factory函数,应用开发人员可以自由定义他们自己的服务。

"service factory function" 对于app应用使用的"service"创建一个单例模式的对象或者函数,注入到依赖特定服务的的任何组件(controller,service,filter或者directive)的服务返回这个对象或者函数。

注册服务

服务通过module API注册到一个module。通常使用module factory API来注册一个服务:

var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
  var shinyNewServiceInstance;
  // 构建服务结构
  return shinyNewServiceInstance;
});

注意这不是注册了一个服务实例,而是一个factory function工厂方法,只有在被调用的时候才会被实例化。

依赖

服务可以有它自己的依赖,就像在controller中声明依赖一样,通过在service的factory方法签名中声明依赖来指定依赖的服务。

更多的依赖介绍,请查看依赖注入文档

下面的module例子有两个服务,各自有各自的依赖:

var batchModule = angular.module('batchModule', []);
/**
 * `batchLog` service 可以对message按照顺序输出
 * 每50s调用一次console.log.
 *
 * @param {*} message 将会被日志输出.
 */
 batchModule.factory('batchLog', ['$interval', '$log', function($interval, $log) {
  var messageQueue = [];

  function log() {
    if (messageQueue.length) {
      $log.log('batchLog messages: ', messageQueue);
      messageQueue = [];
    }
  }

  // 开始循环
  $interval(log, 50000);

  return function(message) {
    messageQueue.push(message);
  }
 }]);
 /**
 * `routeTemplateMonitor` 在每个 `$route` 改变时输出信息
 * 模板通过 `batchLog` service.
 */
 batchModule.factory('routeTemplateMonitor', ['$route', 'batchLog', '$rootScope',
  function($route, batchLog, $rootScope) {
    return {
      startMonitoring: function() {
        $rootScope.$on('$routeChangeSuccess', function() {
          batchLog($route.current ? $route.current.template : null);
        });
      }
    };
  }]);

在这个例子中,注意以下几点:

@1:“batchLog”依赖于内置服务“$interval”和“$log”。

@2:“routeTemplateMonitor”服务依赖于内置服务"$route"和我们创建的服务“batchLog”。

@3:两个服务都是通过数组注解的方式来声明依赖。

@4:数组注解的标识符的顺序和factory函数中的参数的顺序是一致的。

通过$provide注册一个服务

你也可以通过module的config服务中的"$provide"来注册一个服务。

angular.module('myModule', []).config(['$provide', function($provide) {
  $provide.factory('serviceId', function() {
    var shinyNewServiceInstance;
    // 定义服务的主体结构
    return shinyNewServiceInstance;
  });
}]);

这种方式通常被用在单元测试中用来监测服务的依赖。

单元测试

下面是一个根据上面创建angularJS服务例子实现的"notify"的单元测试。这个单元测试使用“Jasmine spy”来模拟真实浏览器中的alert功能。

var mock, notify;
beforeEach(module('myServiceModule'));
beforeEach(function() {
  mock = {alert: jasmine.createSpy()};

  module(function($provide) {
    $provide.value('$window', mock);
  });

  inject(function($injector) {
    notify = $injector.get('notify');
  });
});
it('should not alert first two notifications', function() {
  notify('one');
  notify('two');

  expect(mock.alert).not.toHaveBeenCalled();
});
it('should alert all after third notification', function() {
  notify('one');
  notify('two');
  notify('three');

  expect(mock.alert).toHaveBeenCalledWith("one\ntwo\nthree");
});
it('should clear messages after alert', function() {
  notify('one');
  notify('two');
  notify('third');
  notify('more');
  notify('two');
  notify('third');

  expect(mock.alert.calls.count()).toEqual(2);
  expect(mock.alert.calls.mostRecent().args).toEqual(["more\ntwo\nthird"]);
});


原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(2390)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1