优雅地处理AngularJS错误:$ injector:nomod模块不可用

时间:2015-09-22 23:37:25

标签: angularjs google-analytics adblock

我的角度应用取决于第三方角度服务:

var app = angular.module("ninjaModule", ['angular-google-analytics']);

只要我的广告拦截插件关闭,该应用就可以正常加载。但是,对于角度抛出的广告拦截器出现$injector:nomod错误,无法加载整个应用。

我正在寻找一种优雅地处理这些错误的方法,因此无论广告拦截器如何,都能够加载应用。如果angular-google-analytics不存在 - 那很好,它并不重要,我可以处理它或设置一些后备。但整个应用程序崩溃的情况对我来说不是一个选择。有什么想法吗?

确切地说 - 我不想解决广告拦截器问题,例如:通过重命名我的脚本文件。我期待一个有角度的尝试捕捉魔法技巧。

Plunker:http://plnkr.co/edit/sbEG6vclPidPSNGV5Bsa

3 个答案:

答案 0 :(得分:4)

我终于开始工作了。但是,该解决方案需要一些技巧:

  1. 检查是否加载了angular-google-analytics
  2. 即时为主模块准备依赖关系列表(deps
  3. 明确使用$injector代替Analytics
  4. 但是,我需要配置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();
    });
    

    更新了plunker:http://plnkr.co/edit/Zo4RgKOybzhvJQdW2nQZ?p=preview

答案 1 :(得分:2)

由于angular-google-analytics需要config块来设置帐户,因此您最好的办法是将Google Analytics分析报告分成您应用的单独子模块:

//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

答案 2 :(得分:1)

接受的答案会中断gulp dependency injection,所以我重复一遍,想出一个更独立的方法(你还是需要手动注入这个模块的脚本标签,不管你是依赖吗?在gulp-inject)。

您可以添加依赖项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'); }