Javascript 配置中手动引导和覆盖angular services的问题
我正试图通过覆盖服务,使我的angular应用程序在实时模式和原型模式下工作。当原型模式在配置中打开时,我会停止引导过程,加载模拟服务(js)文件并恢复引导 以下是用于准备的源代码的简化列表:- App.js 只有我的应用程序,用于模拟调用服务并显示结果。它需要Javascript 配置中手动引导和覆盖angular services的问题,javascript,angularjs,angularjs-service,Javascript,Angularjs,Angularjs Service,我正试图通过覆盖服务,使我的angular应用程序在实时模式和原型模式下工作。当原型模式在配置中打开时,我会停止引导过程,加载模拟服务(js)文件并恢复引导 以下是用于准备的源代码的简化列表:- App.js 只有我的应用程序,用于模拟调用服务并显示结果。它需要StubApp以及将使用谁的提供来覆盖服务 DataService.js 只需在应用程序中注册一个简单的服务 Driver.js 只需设置模拟的配置注册 angular.module('app').config(['$provide',
StubApp
以及将使用谁的提供来覆盖服务
DataService.js
只需在应用程序中注册一个简单的服务
Driver.js
只需设置模拟的配置注册
angular.module('app').config(['$provide', 'stubServiceProvider', 'AppConfig', function($provide, stubProvider, AppConfig){
if(AppConfig.StubEnabled){
stubProvider.loadStubsInModule('plunker');
}
}]);
StubProvider.js
这将公开一个类似于angular.module
的接口来注册存根服务。它还查找stubs.json
,其中包含通过停止引导加载的模拟服务列表。它还公开了一个provide,应用程序可以使用它设置stubs.json中现有服务的过载
DataService Mock.js
这仅仅是一个mock,它实际使用Stubs接口来注册mockStubs.module('app').mock(MockService)
,并且ctor有一个属性stubFor=“serviceName”
,它告诉我们它实际模拟的是哪个服务
stubs.json
只是一个简单的json文件,用于指定模拟
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
之前以index.html模式Driver.js
复制该问题,它不会用MockDataservice覆盖DataService
- 为什么配置注册的顺序很重要,配置阶段应该在服务实例化正确之前运行?
- 是否有更好的模式确保在恢复引导过程之前加载所有脚本,而不是使用延迟模式
createElement
和appendChild
DOM方法、src
和onload
属性以及AngularJS的bootstrap
、元素
和injector
方法:
/*创建脚本元素*/
var script=document.createElement('script');
/*设置src*/
script.src=”https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js";
/*附在头上*/
document.getElementsByTagName(“head”)[0].appendChild(脚本);
函数dothis()
{
//本地数据存储
this.mvvm={};
//模板字符串
var html=“ID:{{$ID}}”。替换(“|“,”,“g”);
//模板对象
var template=angular.element(html);
//模板转换器
var compiler=angular.injector([“ng”]).get(“$compile”);
//模板结果
var linker=编译器(模板);
//范围对象
var scope=angular.injector([“ng”]).get($rootScope”);
//范围绑定
var结果=链接器(范围)[0];
/*将结果附加到正文*/
document.body.appendChild(结果);
/*渲染*/
引导(文档,['ng']);
}
script.onload=dothis;
我喜欢这个问题,因为我现在无法回答。我一直在玩你的代码,我有一个问题。你为什么不创建一个新模块,提供你想要覆盖的所有内容,从主模块到刚刚创建的模块,然后将模块名传递给resumeBootstrap函数?这样你就可以uld能够覆盖以前定义的所有名称。它应该更干净。我想到的另一个选择是使用装饰器,但我认为它们不适用于您的场景。干杯!希望有一个更好的答案来给Sooon更多值得注意的东西,angular.injector()启动应用程序,但我不知道当window.name是NG_DEFER_BOOTSTRAP时它的行为是什么!@HeberLZ谢谢你的建议,实际上听起来是个好主意。我还没有尝试过。但是如果你得到一个好的/更好的解决方案,请作为答案发布。我的主要问题是,我不想在html st中加载模拟控制器的脚本当然。我会动态加载它。再次感谢。提供引导的想法是,在我们调用resumeBootstrap之前,引导不会启动。我认为问题不在引导流程中,而是在注入器创建过程中。我之所以这样说,是因为我试着根本不同步引导应用程序,而是执行引导手动关闭,结果完全相同。另一方面,我必须在执行时声明注入器,它们像并行应用程序一样工作,这就是为什么我认为这可能是导致这种奇怪行为的原因。稍后我将尝试一些方法,如果结果是肯定的,则显示结果。干杯!
angular.module('app').config(['$provide', 'stubServiceProvider', 'AppConfig', function($provide, stubProvider, AppConfig){
if(AppConfig.StubEnabled){
stubProvider.loadStubsInModule('plunker');
}
}]);
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
});
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);
["DataServiceMock.js"]
<script src="app.js"></script>
<script src="DataService.js"></script>
<script src="Driver.js"></script>
<script src="stubprovider.js"></script>
Stubs.module(moduleName).get().forEach(function (mod) {
var serviceName = mod.stubFor;
var ctor = mod;
if (serviceName) {
$provide.service(serviceName, ctor);
}
});