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 魔术。

笨蛋:http://plnkr.co/edit/sbEG6vclPidPSNGV5Bsa

由于 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

我终于让它工作了。不过,该解决方案需要一些技巧:

  1. 正在检查 angular-google-分析是否已加载
  2. 正在为主模块即时准备依赖列表(deps
  3. 明确使用 $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();
});

更新的插件:http://plnkr.co/edit/Zo4RgKOybzhvJQdW2nQZ?p=preview

已接受的答案中断了 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'); }