Проблема с ручной загрузкой и переопределением угловых сервисов в конфигурации
Я пытаюсь заставить мое угловое приложение работать в режиме реального времени, а также в режиме прототипа, просто переопределяя службы. Как часть этого, когда режим прототипа включен в конфигурации, я остановил процесс начальной загрузки, загрузил файлы mock services (js) и возобновил загрузку.
Вот упрощенный список исходного кода для подготовки демонстрации:
App.js
Просто мое приложение, которое для симуляции вызывает сервис и отображает результат. Требуется StubApp
а также, чье обеспечение это собирается использовать для переопределения услуг
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
Просто регистрация конфигурации, которая будет настраивать насмешки.
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.
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.module('app').mock(MockService)
и у ctor есть свойство stubFor="serviceName"
который говорит, какой сервис это на самом деле издевается
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"
Stubs.module(moduleName).get().forEach(function (mod) {
var serviceName = mod.stubFor;
var ctor = mod;
if (serviceName) {
$provide.service(serviceName, ctor);
}
});
Вот демо Plnkr Если вы закомментируете строку в Driver.js
вы можете видеть, что выходные данные будут получены от реального сервиса, в противном случае это будет макетный сервис. И повторить проблему в режиме index.html Driver.js
до DataService.js
он не отменяет DataService с MockDataservice.
Почему порядок регистрации конфигурации имеет значение, фаза конфигурации должна выполняться до того, как экземпляр службы все равно будет корректным?
Есть ли лучший шаблон, чтобы убедиться, что все сценарии загружены перед возобновлением процесса начальной загрузки, а не с использованием отложенного шаблона.
1 ответ
Использовать createElement
а также appendChild
DOM методы, src
а также onload
атрибуты script
элемент, а bootstrap
, element
а также injector
методы 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;