Graceful handling with AngularJS Error: $ injector: nomod Module unavailable

My angular application depends on a third-party angular service:

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

The application loads just fine while my ad blocking plugins are disabled. However, from ad-blockers to angular it throws a $injector:nomod without loading the entire application.

I am looking for a way to gracefully handle these errors and therefore be able to download the application regardless of ad units. If angular-google-analytics is not there - great, this is not critical, I can handle it or set up some reserve. But a situation where all application crashes is not suitable for me. Any ideas?

To be precise - I do not want to work with ad units, for example. renaming my script files. I was expecting an angular try-catch magic trick.

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

+6
source share
3 answers

Finally, I started to work. The solution requires several hacks:

  • check for angular -google-analytics
  • preparing a list of dependencies ( deps ) for the main module on the fly
  • using $injector instead of $injector explicitly

However, I need to configure AnalyticsProvider , but this should be relatively easy to do with the $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(); }); 

Updated plunker: http://plnkr.co/edit/Zo4RgKOybzhvJQdW2nQZ?p=preview

+4
source

Since angular-google-analytics requires a config block to set up an account, it’s best to separate the Google Analytics reporting into a separate sub-module of your application:

 //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'); }); 

And then add this submodule to your main module asynchronously through the module.requires array so that it starts after the main load module completes:

 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); 

Thus, the main module completes the download without errors associated with the submodule message.

Here's a forked version of your plunkr: http://plnkr.co/edit/lgNZOz4MZx0FGoCOGRC9

+2
source

The accepted answer interrupts gulp dependency injection , so I repeated it to come up with a more autonomous method (you still need to enter this script tag manually, but if you rely on gulp-inject ).

You can add the dependency dynamically , and you can completely stop using the $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'); } 
+1
source

All Articles