angular:写一个嘲弄我真实后端的服务

时间:2014-10-21 01:03:05

标签: angularjs dependency-injection angularjs-service

我需要编写访问后端数据的代码。

麻烦的是后端还没有准备好。所以我想注入一个服务,可能通过配置,使用真正的后端或模拟对象。

我认为角度服务是我需要的。但我不清楚如何实现这一点。

app.factory('myService', function() {
  var mySrv;

  //if backend is live, get the data from there with $http
  //else get data from a mock json object
  return mySrv;
});

不知怎的,我想我必须再写两个服务,真正的服务和假服务,然后在'myService'中调用其中一个服务?

也许我完全误解了嘲讽,但我宁愿不要为测试运行而嘲笑它(不适用于这篇文章中的单元测试:Injecting a mock into an AngularJS service - 我希望应用程序真正使用我的模拟用于演示和开发目的。

2 个答案:

答案 0 :(得分:1)

这实际上是Angular的依赖注入系统真正派上用场的地方。 Angular中的所有内容在某种程度上基本上都是provider服务和工厂等方法只是避免样板代码的便捷函数。

可以在引导过程中配置提供程序,这对于设置与您所描述的内容完全相同的方案非常方便。

最简单的是,提供程序只需要是一个构造函数,它可以创建一个具有 $get 功能的对象。 $get是创建实际服务的地方,您可以在此处查看要创建的服务。

//A simple provider
function DataServiceProvider(){

  var _this = this;

  _this.$get = function(){
    //Use configured value to decide which
    // service to return
    return _this.useMock ? 
             new MockService() : 
             new RealService;
  };

}

现在,您可以将其注册为应用程序模块的提供程序。

angular.module('my-module', [])
  .provider('dataService', DataServiceProvider);

可以在创建第一个服务实例之前配置提供程序。 按照惯例,提供商将以NAME + 'Provider'

的形式提供
angular.module('my-module')
  .config(['dataServiceProvider', function(dataServiceProvider){
    //Set the flag to use mock service
    dataServiceProvider.useMock = true;
  }]);

现在,无论何时在应用程序中的任何位置注入dataService,它都将使用您根据配置提供的模拟服务。

您可以在下面的代码段中看到完整工作示例

(function(){

  function RealService(){
    this.description = 'I\'m the real McCoy!';
  }
  
  function MockService(){
    this.description = 'I\'m a shady imposter :P';
  }
  
  function DataServiceProvider(){
    var $this = this;
    
    $this.useMock = false;
    
    $this.$get = function(){
      return $this.useMock ?
          new MockService() :
          new RealService();
    };
  }
  
  function CommonController(dataService){
    this.dataServiceDescription = dataService.description;
  }
  CommonController.$inject = ['dataService'];
  
  angular.module('common', [])
    .provider('dataService', DataServiceProvider)
    .controller('commonCtrl', CommonController);
  
  angular.module('provider-app-real-service', ['common'])
    .config(['dataServiceProvider', function(dataServiceProvider){
      dataServiceProvider.useMock = false;
    }]);
  
  angular.module('provider-app-mock-service', ['common'])
    .config(['dataServiceProvider', function(dataServiceProvider){
      dataServiceProvider.useMock = true;
    }]);
  
  
  var moduleNames = ['provider-app-real-service','provider-app-mock-service'];
    
  angular.forEach(moduleNames, function(modName){
    //Have to manually bootstrap because Angular only does one by default
    angular.bootstrap(document.getElementById(modName),[modName]);
  }); 
  
}());
<script src="http://code.angularjs.org/1.3.0/angular.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" />

<div class="container">
  <div class="row" id="provider-app-real-service">
    <div class="col-sm-12" ng-controller="commonCtrl as ctrl">
      <h1>{{ctrl.dataServiceDescription}}</h1>
    </div>
  </div>
  <div class="row" id="provider-app-mock-service">
    <div class="col-sm-12" ng-controller="commonCtrl as ctrl">
      <h1>{{ctrl.dataServiceDescription}}</h1>
    </div>
  </div>
</div>

答案 1 :(得分:0)

这需要是一项服务吗?如果你想创建一个模拟服务,那么Josh的上述答案是完美的。

如果您不喜欢使用某项服务,那么我建议您查看以下问题Mock backend for Angular / Gulp app的答案,该问题也是关于嘲笑后端的问题。无论你的后端是创建的还是没有嘲笑它,都可以让你更加稳定的测试运行和app的开发。