简体   繁体   English

Angular-使用ngNotificationsBar时发现循环依赖

[英]Angular - Circular dependency found when using ngNotificationsBar

I try to use ng-notifications-bar module, I have code like this: 我尝试使用ng-notifications-bar模块,我有这样的代码:

angular.module('app', [
    uiRouter,
    Common.name,
    Components.name,
    angularMaterial,
    'ngTable',
    'gridster',
    'ngNotificationsBar'
  ])
  .factory('$exceptionHandler', ['notifications', function(notifications) {
    return function(exception, cause) {
      notifications.showError({message: exception});
    };
  }]);

but got error: 但出现错误:

[$injector:cdep] Circular dependency found: $rootScope <- notifications <- $exceptionHandler <- $rootScope <- $timeout <- $$rAF <- $mdGesture [$ injector:cdep]发现循环依赖项:$ rootScope <-通知<-$ exceptionHandler <-$ rootScope <-$ timeout <-$$ rAF <-$ mdGesture

I've tried to modify the library to use $injector to get $timeout and $rootScope but that didn't help also tried to use $injector to get notifications in $exceptionHandler factory but got the same error. 我试图修改该库以使用$injector来获取$ timeout和$ rootScope,但这也无济于事,还试图使用$injector来获取$exceptionHandler工厂中的notifications ,但出现了相同的错误。

Pretty poor design from angular it looks on this one. 从角度来看,这是一个很差的设计。 You can't inject $rootScope in any form into $exceptionHandler due to the dependency. 由于依赖关系,您不能以任何形式将$rootScope注入$exceptionHandler

You can use $injector to get around these kinds of (out-of-your-hands) dependency problems, you just need to make sure that the injected module is used inside the return function to ensure that at the time of calling .get() the dependent module has actually loaded. 您可以使用$injector来解决这类(无法使用的)依赖关系问题,您只需要确保在return函数内部使用注入的模块即可确保在调用.get()相关模块已实际加载。 For example: 例如:

// won't not be available here
var rootScope = $injector.get('$rootScope');

return function(exception, cause) {
  // will be available here
  var rootScope = $injector.get('$rootScope');
};

This is because $injector is used to grab the dependency at run time. 这是因为$injector用于在运行时获取依赖项。

There is a nice clean object-oriented design to avoid circular dependencies: use the dependency inversion principle . 有一个很好的干净的面向对象设计可以避免循环依赖:使用依赖反转原理 Create a generic service to which you can attach handlers, and set it up from a run block. 创建可以将处理程序附加到的常规服务,然后从run块对其进行设置。 Basically all the other solutions suggest something similar, but with using global variables outside of angular, or bypassing the automatic dependency injection. 基本上所有其他解决方案都提出了类似的建议,但使用了超出角度的全局变量或绕过了自动依赖项注入。

 angular.module("App", []) .factory("notifications", function($rootScope) { $rootScope.notifications = []; function showMessage(msg) { $rootScope.notifications.push(msg); } return { showMessage }; }) .factory("$exceptionHandler", function(MyExceptionService) { return function(e, cause) { MyExceptionService.fire(e, cause); }; }) .factory("MyExceptionService", function() { const handlers = []; return { addHandler(h) { handlers.push(h); }, fire(e, cause) { handlers.forEach(h => { h(e, cause); }) } }; }) .controller("MyCtrl", function($scope) { $scope.clicked = () => { throw new Error("Error made"); }; }) .run(function(MyExceptionService, notifications) { MyExceptionService.addHandler(err => { notifications.showMessage({ message: err.message }); }); }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script> <div ng-app="App" ng-controller="MyCtrl"> <button ng-click="clicked()">Make Error</button> <div>Errors:</div> <div ng-repeat="item in notifications">{{item}}</div> </div> 

For comparison, here is the wrong one (with the circular dependency): 为了进行比较,这是错误的(具有循环依赖性):

 angular.module("App", []) .factory("notifications", function($rootScope) { $rootScope.notifications = []; function showMessage(msg) { $rootScope.notifications.push(msg); } return { showMessage }; }) .factory("$exceptionHandler", function(notifications) { return function(e, cause) { notifications.showMessage({ message: err.message }); }; }) .controller("MyCtrl", function($scope) { $scope.clicked = () => { throw new Error("Error made"); }; }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script> <div ng-app="App" ng-controller="MyCtrl"> <button ng-click="clicked()">Make Error</button> <div>Errors:</div> <div ng-repeat="item in notifications">{{item}}</div> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM