Gracefully handling AngularJS Error: $injector:nomod Module Unavailable
Gracefully handling AngularJS Error: $injector:nomod Module Unavailable
我的 angular 应用依赖第三方 angular 服务:
var app = angular.module("ninjaModule", ['angular-google-analytics']);
只要我的广告拦截插件关闭,该应用程序就可以正常加载。但是,angular 上的广告拦截器会引发 $injector:nomod
错误,无法加载整个应用程序。
我正在寻找一种优雅地处理这些错误的方法,因此能够在不受广告拦截器影响的情况下加载应用程序。如果 angular-google-analytics 不存在 - 好吧,这并不重要,我可以处理它或设置一些后备。但是整个应用程序崩溃的情况对我来说不是一个选项。有什么想法吗?
准确地说 - 我不想绕过广告拦截器,例如通过重命名我的脚本文件。我期待一个 angular try-catch 魔术。
由于 angular-google-analytics
需要 config
块来设置帐户,最好的办法是将 google 分析报告分离到应用程序的单独子模块中:
//create separate module for analytics reporting
var reportingModule = angular.module('mainApp.reporting', [
'angular-google-analytics'
])
.config(function(AnalyticsProvider) {
AnalyticsProvider.setAccount('UA-HELLO-GA');
})
.run(function(Analytics) {
console.log('mmm.. analytics is good for you');
});
然后通过 module.requires
数组将此子模块异步注入主模块,使其在主模块完成引导后运行:
var mainApp = angular.module('mainApp', [
])
.controller('MyCtrl', function($scope) {
$scope.message = 'Hello World!';
});
//set the dependency after app finished bootstrapping
setTimeout(function() {
angular.module('mainApp').requires.push('myapp.reporting');
}, 1);
这样主模块就可以完成引导,而不会受到报告子模块错误的影响。
这是你的 plunkr 的分叉版本:http://plnkr.co/edit/lgNZOz4MZx0FGoCOGRC9
我终于让它工作了。不过,该解决方案需要一些技巧:
- 正在检查 angular-google-分析是否已加载
- 正在为主模块即时准备依赖列表(
deps
)
- 明确使用
$injector
而不是 Analytics
仍然,我需要配置 AnalyticsProvider
,但使用 $injector
应该相对容易。
var deps = [];
try {
angular.module("angular-google-analytics"); // this throws if GA script is not loaded
deps.push('angular-google-analytics');
} catch(e){ console.error("GA not available", e); }
angular.module('mainApp', deps)
.run(function($rootScope, $injector) {
try {
Analytics = $injector.get('Analytics');
$rootScope.trackPage = function() {
console.log('Analytics in action!');
Analytics.trackPage();
}
} catch(e) {
$rootScope.trackPage = function(key, label) {
console.log("Fallback in action!")
}
}
})
.controller('MyCtrl', function($rootScope, $scope) {
$scope.message = 'Hello World!';
$rootScope.trackPage();
});
已接受的答案中断了 gulp dependency injection 所以我对其进行了迭代以提出一个更独立的方法(如果您依赖 [=11,您仍然需要手动注入此模块的脚本标签=]).
你可以添加依赖dynamically,你可以完全避免使用$injector
。
angular.module('app', [
'your',
'regular',
'dependencies'
])
.config(function(...) {
/*your normal code*/
})
.run(function(...) {
/*with no concern for analytics*/
})
//mimicking your answer for equivalence
.controller('MyCtrl', function($rootScope) {
if ($rootScope.Analytics)
$rootScope.Analytics.trackPage();
})
;
//protect against adblockers
try {
//throws if not available
angular.module('angular-google-analytics');
//dynamically add the dependency
angular.module('app').requires.push('angular-google-analytics');
//set it up
angular.module('app')
.config(function (AnalyticsProvider) {
AnalyticsProvider.setAccount('UA-00000000-0');
})
//so we dont need to use $injector
.run(function(Analytics, $rootScope) {
$rootScope.Analytics = Analytics;
})
;
} catch(e) { console.error('GA not available'); }
我的 angular 应用依赖第三方 angular 服务:
var app = angular.module("ninjaModule", ['angular-google-analytics']);
只要我的广告拦截插件关闭,该应用程序就可以正常加载。但是,angular 上的广告拦截器会引发 $injector:nomod
错误,无法加载整个应用程序。
我正在寻找一种优雅地处理这些错误的方法,因此能够在不受广告拦截器影响的情况下加载应用程序。如果 angular-google-analytics 不存在 - 好吧,这并不重要,我可以处理它或设置一些后备。但是整个应用程序崩溃的情况对我来说不是一个选项。有什么想法吗?
准确地说 - 我不想绕过广告拦截器,例如通过重命名我的脚本文件。我期待一个 angular try-catch 魔术。
由于 angular-google-analytics
需要 config
块来设置帐户,最好的办法是将 google 分析报告分离到应用程序的单独子模块中:
//create separate module for analytics reporting
var reportingModule = angular.module('mainApp.reporting', [
'angular-google-analytics'
])
.config(function(AnalyticsProvider) {
AnalyticsProvider.setAccount('UA-HELLO-GA');
})
.run(function(Analytics) {
console.log('mmm.. analytics is good for you');
});
然后通过 module.requires
数组将此子模块异步注入主模块,使其在主模块完成引导后运行:
var mainApp = angular.module('mainApp', [
])
.controller('MyCtrl', function($scope) {
$scope.message = 'Hello World!';
});
//set the dependency after app finished bootstrapping
setTimeout(function() {
angular.module('mainApp').requires.push('myapp.reporting');
}, 1);
这样主模块就可以完成引导,而不会受到报告子模块错误的影响。
这是你的 plunkr 的分叉版本:http://plnkr.co/edit/lgNZOz4MZx0FGoCOGRC9
我终于让它工作了。不过,该解决方案需要一些技巧:
- 正在检查 angular-google-分析是否已加载
- 正在为主模块即时准备依赖列表(
deps
) - 明确使用
$injector
而不是Analytics
仍然,我需要配置 AnalyticsProvider
,但使用 $injector
应该相对容易。
var deps = [];
try {
angular.module("angular-google-analytics"); // this throws if GA script is not loaded
deps.push('angular-google-analytics');
} catch(e){ console.error("GA not available", e); }
angular.module('mainApp', deps)
.run(function($rootScope, $injector) {
try {
Analytics = $injector.get('Analytics');
$rootScope.trackPage = function() {
console.log('Analytics in action!');
Analytics.trackPage();
}
} catch(e) {
$rootScope.trackPage = function(key, label) {
console.log("Fallback in action!")
}
}
})
.controller('MyCtrl', function($rootScope, $scope) {
$scope.message = 'Hello World!';
$rootScope.trackPage();
});
已接受的答案中断了 gulp dependency injection 所以我对其进行了迭代以提出一个更独立的方法(如果您依赖 [=11,您仍然需要手动注入此模块的脚本标签=]).
你可以添加依赖dynamically,你可以完全避免使用$injector
。
angular.module('app', [
'your',
'regular',
'dependencies'
])
.config(function(...) {
/*your normal code*/
})
.run(function(...) {
/*with no concern for analytics*/
})
//mimicking your answer for equivalence
.controller('MyCtrl', function($rootScope) {
if ($rootScope.Analytics)
$rootScope.Analytics.trackPage();
})
;
//protect against adblockers
try {
//throws if not available
angular.module('angular-google-analytics');
//dynamically add the dependency
angular.module('app').requires.push('angular-google-analytics');
//set it up
angular.module('app')
.config(function (AnalyticsProvider) {
AnalyticsProvider.setAccount('UA-00000000-0');
})
//so we dont need to use $injector
.run(function(Analytics, $rootScope) {
$rootScope.Analytics = Analytics;
})
;
} catch(e) { console.error('GA not available'); }