配置中手动引导和覆盖角度服务的问题 [英] Issue with manual bootstrapping and overriding angular services in config

查看:23
本文介绍了配置中手动引导和覆盖角度服务的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过覆盖服务来让我的 Angular 应用程序在实时模式和原型模式下工作.作为其中的一部分,当在配置中打开原型模式时,我停止引导过程,加载模拟服务 (js) 文件并恢复引导.

I am trying to get my angular application work in live mode as well as in a prototype mode just by overriding the services. As a part of this when the prototype mode is turned on in the config, i halt the bootstrap process, load mock services (js) files and resume bootstrapping.

这是准备演示:-

Here is a simplified list of source code for preparing the demo:-

App.js

只是我的应用程序,用于模拟调用服务并显示结果.它需要 StubApp 以及其将用于覆盖服务的提供

Just my app, which for simulation calls the service and display the result. It required StubApp as well whose provide this is going to use to override the services

var app = angular.module('app', ['StubsApp'])

.run([ '$rootScope', 'DataService', function($scope, DataService){
   DataService.getData().then(function(data){
    $scope.name = data;
  });
}]);

DataService.js

只是一个向应用注册的简单服务.

function DataService($q){
  this.getData = function(){
       return $q.when('I am Real!!');
  }
}
DataService.$inject = ['$q'];
angular.module('app').service('DataService',DataService);

Driver.js

只需配置注册即可设置模拟.

Just the config registration which will set up mocking.

angular.module('app').config(['$provide', 'stubServiceProvider', 'AppConfig', function($provide, stubProvider, AppConfig){
    if(AppConfig.StubEnabled){
       stubProvider.loadStubsInModule('plunker');
    }
}]);

StubProvider.js

这暴露了一个类似于 angular.module 的接口来注册存根服务.它还查找 stubs.json ,其中包含通过停止引导程序加载的模拟服务列表.它还公开了一个提供程序,应用程序可以使用它来设置现有服务与 stubs.json 中的服务的重载

This exposes an interface similar to angular.module to register stub services. it also looks for stubs.json which has the list of mock services which is loaded by halting the bootstrap. It also exposes a provide which an App can use to set up overload of existing services with the ones in the stubs.json

var Stubs = {},
    modules = [];
function module(moduleName) {
    return {
        mock: function (func) {
            modules.push(func);
        }, get: function () {
            return modules;
        }
    };
}
Stubs.module = module;

loadStubs();

function loadStubs() {
    window.name = "NG_DEFER_BOOTSTRAP!";
    var injector = angular.injector(['ng']);
    var $q = injector.get('$q');
    var $http = injector.get('$http');
    var scripts = [];

    $http.get('stubs.json').then(function (result) {
        scripts = result.data.map(function (src) {
            var script = document.createElement('script');
            script.src = src;
            script.async = true;
            document.head.appendChild(script);

            var defered = $q.defer();

            script.onload = function () {
                defered.resolve();
            };
            return defered.promise;
        });

        $q.all(scripts).finally(function () {
            angular.element().ready(function () {
                angular.resumeBootstrap();
            });
        });
    });
}

//This is the provider which actually will do the overriding
angular.module('StubsApp', []).provider('stubService', function ($provide) {
    ...... //Code in plunker
});

DataService Mock.js

这只是一个模拟,它实际上使用 Stubs 接口来注册模拟 Stubs.module('app').mock(MockService) 并且 ctor 有一个属性 stubFor="serviceName" 告诉它实际上模拟了哪个服务

This is the just a mock which actually uses Stubs interface to register the mock Stubs.module('app').mock(MockService) and the ctor has a property stubFor="serviceName" which tells which service this actually mocks

function MockService($q, $log){
this.getData = function(){
       return $q.when('I am Mock!!');
  }
}
MockService.$inject = ['$q', '$log'];

MockService.stubFor="DataService";

Stubs.module('app').mock(MockService);

stubs.json

只是一个简单的 json 文件,指定了模拟

["DataServiceMock.js"]

index.html

<script src="app.js"></script>
<script src="DataService.js"></script>
<script src="Driver.js"></script>
<script src="stubprovider.js"></script>

这很好用.现在的问题是,当我在服务注册之前移动 Driver.js 文件 DataService.js 它不会再模拟了.在StubProvider.js"中执行覆盖的代码的特定部分是

This works fine. Now the issue is that when i move Driver.js file before the service registration i.e DataService.js it won't mock anymore. Specific portion of code that performs overriding in the "StubProvider.js" is

   Stubs.module(moduleName).get().forEach(function (mod) {
        var serviceName = mod.stubFor;
        var ctor = mod;
        if (serviceName) {
            $provide.service(serviceName, ctor);
        }
    });

这是一个 Demo Plnkr 如果你注释掉Driver.js 中的行,您可以看到输出将来自真实服务,否则它将来自模拟服务.并在 DataService.js 之前在 index.html 模式 Driver.js 中复制问题,它不会用 MockDataservice 覆盖 DataService.

Here is a Demo Plnkr If you comment out the line in the Driver.js you can see the output will be from the real service other wise it will be from the mock service. And to replicate the issue in the index.html mode Driver.js before DataService.js it won't override DataService with MockDataservice.

  • 为什么配置注册的顺序很重要,配置阶段应该在服务实例化之前运行?

是否有更好的模式来确保在恢复引导过程之前加载所有脚本而不是使用延迟模式.

Is there a better pattern to ensure all the scripts are loaded before resuming the bootstrap process rather than using the deferred pattern.

推荐答案

使用 createElementappendChild DOM 方法,src 和 <script 元素的 code>onload 属性,以及 bootstrapelementinjector 方法AngularJS:

Use the createElement and appendChild DOM methods, the src and onload attributes of the script element, and the bootstrap, element and injector methods of AngularJS:

    /* Create script element */
    var script = document.createElement('script');
    /* Set src */
    script.src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js";
    /* Append to head */
    document.getElementsByTagName("head")[0].appendChild(script);
    
    function dothis()
      {
      //local datastore
      this.mvvm = {};
    
      //template string
      var html = "<div>ID: {{$id}}</div>".replace("|",'"',"g");
      //template object
      var template = angular.element(html);
      //template transformer
      var compiler = angular.injector(["ng"]).get("$compile");
      //template result
      var linker = compiler(template);
      //scope object
      var scope = angular.injector(["ng"]).get("$rootScope");
      //scope binding
      var result = linker(scope)[0];
    
      /* Append result to body */
      document.body.appendChild(result);
    
      /* Render */
      angular.bootstrap(document, ['ng']);
      }
    
    script.onload = dothis;

这篇关于配置中手动引导和覆盖角度服务的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆