【问题标题】:AngularJS circular dependencyAngularJS 循环依赖
【发布时间】:2014-05-19 11:09:59
【问题描述】:

我正在制作一个记录器服务,通过将错误(或调试,如果启用)保存到 indexedDB 数据库来扩展 angular 的 $log 服务。代码如下:

angular.module('appLogger', ['appDatabase'])

.service('LogServices', function($log, Database) {

    // ...

    this.log = function(type, message, details) {
        var log = {};
        log.type = type
        log.context = this.context;
        log.message = message;
        log.dateTime = moment().format('YYYY-MM-DD HH:mm:ss');
        log.details = details || '';
        $log[type.toLowerCase()](log);

        if (type === 'ERROR' || this.logDebug) {
            Database.logSave(log);
        }
    };

    // ...
})

这在我的服务中按预期工作。现在的问题是我不能在数据库服务中使用我的记录器,因为它会引发循环依赖错误。我明白这个问题,但我不知道我应该如何解决它......我应该如何解决这个问题?

感谢您的帮助:-)

【问题讨论】:

标签: angularjs circular-dependency


【解决方案1】:

我在尝试覆盖 exceptionHandler 时遇到了这个问题

这是出现问题的代码

angular
    .factory('$exceptionHandler', ExceptionHandler);

function exceptionHandler($log, sweetAlert) {// here is the problem with injecting sweetAlert
    return function myExceptionHandler(exception, cause) {
        //logErrorsToBackend(exception, cause);
        sweetAlert.swal('Opps...', 'An error has occurred');
        $log.warn(exception, cause);
    };
}

为了修复它,我使用了injector

angular
    .factory('$exceptionHandler', ExceptionHandler);

ExceptionHandler.$inject = ['$injector']; //better for minification

function ExceptionHandler($injector) {
    var $log, sweetAlert, $translate;// use variables for caching

    return function exceptionHandler(exception, cause) {
        // Add DI here to prevent circular dependency
        $log = $log || $injector.get('$log');
        sweetAlert = sweetAlert || $injector.get('sweetAlert');
        $translate = $translate || $injector.get('$translate');
        //............
    }

这里是更多信息的链接Injecting $http results in a Circular dependency

希望对你有帮助

【讨论】:

    【解决方案2】:

    请参阅this answer,尤其是Misko's blog,尤其是彼得在 cmets 中的问题,其中讨论了几乎完全相同的问题。

    Misko 的回答是(使用 Java 代码)

    class Database() implements DB;
    class Logger(Database db);
    class LoggingDatabase(Logger log, Database db) implements DB;
    

    所以在你的应用程序中,你有

    .service('Database', ...) // DO NOT inject the $log or LogServices here
    
    .service('LogServices', function($log) {...}) // DO NOT inject Database here
    
    .service('LoggingDB', function(Database, LogServices) {...}) 
    

    在您需要记录数据库的应用程序的每个部分都使用 LoggingDB。 (或者是使用数据库的记录器!)

    另一个想法

    您在浏览器上有一个数据库是怎么回事?数据库是 $http 或 $resource 的包装器吗?如果是这种情况,我同意 ExpertSystem 在他的 2) 选项中:不要使用 $http 记录错误,因为如果错误杀死 $http 怎么办?请改用 XMLHTTPRequest。请参阅here 进行一些讨论。

    【讨论】:

      【解决方案3】:

      Angular 抱怨循环依赖的原因是……嗯,有一个。
      这是一条非常危险的道路,但是如果您知道自己在做什么(著名的遗言),那么有一个解决方案可以规避:

      .service('LogServices', function($log, $injector) {
      
          // ...
      
          var Database;   // Will initialize it later
      
          this.log = function(type, message, details) {
              /* Before using Database for the first time
               * we need to inject it */
              if (!Database) { Database = $injector.get('Database'); }
      
              var log = {};
              log.type = type
              log.context = this.context;
              log.message = message;
              log.dateTime = moment().format('YYYY-MM-DD HH:mm:ss');
              log.details = details || '';
              $log[type.toLowerCase()](log);
      
              if (type === 'ERROR' || this.logDebug) {
                  Database.logSave(log);
              }
          };
      
          // ...
      })
      

      另请参阅此short demo。

      【讨论】:

      • 谢谢,它是这样工作的。现在你认为什么是安全的路径?为什么这条路很危险?你能详细说明一下吗?我非常想以有角度的方式做事,如果可能的话,不要使用黑客。问题是,我还有其他选择吗?
      • 危险的事情是进入一个无限循环,这会破坏你的应用程序(这就是 Angular 首先试图保护你的东西)。如果您想看到它的实际效果,请转到我的演示并取消注释 service1.serve(); 行“Angular”方式不是创建循环依赖项(在这种情况下,我认为您不能,因为您需要 Database提供LogServices,并且您还希望在Database 中提供LogServices(这本身就是一个悖论:))。
      • 如果你想“安全行事”,我看到 2 个选项:1.) 对于 Database,使用更简单的日志机制(不依赖于 Database)。 2.) 不要为LogServices 和应用程序的其余部分使用相同的Database 服务。使用更简单的LogDatabase 服务(不依赖于LogServices)传递给LogServices,并将您当前的Database 服务用于应用程序的其余部分(可以安全地使用LogServices 进行日志记录)。 (我希望这是有道理的:P)
      • 我想我必须手动保存错误,而不是依赖数据库服务。我不能反过来做,因为数据库服务很大,因此严重依赖日志记录。该死的,我以为会有一个替代方案。无论如何,谢谢你的提醒:)
      猜你喜欢
      • 2014-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-21
      • 2010-09-12
      • 2021-10-02
      相关资源
      最近更新 更多