2014-04-07 2 views
12

나는 오류 (또는 사용 가능하다면 디버그)를 indexedDB 데이터베이스에 저장하여 logger 서비스를 만들고 Angular의 $ log 서비스를 확장하려고합니다. 코드는 다음과 같습니다.AngularJS circular dependency

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

    // ... 
}) 

이것은 의도 한대로 작동합니다. 이제 문제는 순환 종속성 오류가 발생하기 때문에 데이터베이스 서비스에서 내 로거를 사용할 수 없다는 것입니다. 나는 문제를 이해하지만 어떻게 해결해야하는지 아무 단서도 없다 ...이 문제를 어떻게 해결해야합니까? :-)

+1

비슷한 질문에 대한 제 대답을보십시오 : http://stackoverflow.com/questions/20647483/angularjs-injecting-service-into-a-http-interceptor-circular-dependency/ 21632161 # 21632161 –

답변

28

각도 이유를 돕는

덕분에 순환 종속성이 아니라 하나가 ...이다에 대해 불평한다.
아래로 갈 수있는 매우 위험한 경로입니다,하지만 당신은 당신이 (유명한 마지막 말을) 무엇을하고 있는지 알고있는 경우에 그를 우회 할 수있는 해결책이 :

.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은.

+0

고맙습니다. 이런 식으로 일하고 있습니다. 이제 안전 경로가 무엇이라고 생각하십니까? 이 길은 왜 위험한가요? 제발 좀 더 자세히 설명해 주실 수 있습니까? 나는 대각선으로 할 일을하고, 가능하다면 해킹을 사용하지 않기를 바란다. 질문은, 다른 옵션이 있습니까? – ImSoNuts

+3

위험한 것은 앱을 부술 수있는 무한 루프에 빠지게하는 것입니다 (Angular가 처음부터 당신을 보호하려고 시도하는 것입니다). 이 동작을보고 싶다면 내 데모로 가서'service1.serve(); '줄의 주석 처리를 제거하십시오. "각도"방식은 순환 종속성을 생성하는 것이 아닙니다 (이 경우에는 생각할 수 없습니다. 'LogServices'를 제공하기 위해'Database'가 필요하고'Database'에서'LogServices'를 사용할 수 있습니다 (이것은 역설적입니다 :)). – gkalpak

+1

만약 당신이 "안전하게 플레이"하고 싶다면, 2 가지 옵션이 있습니다 : 1.)'Database'는 더 간단한 로깅 메커니즘을 사용합니다 ('Database'에 의존하지 않습니다). 2.)'LogServices'와 나머지 응용 프로그램에서 동일한 'Database' 서비스를 사용하지 마십시오. 'LogServices'에 전달하지 않는 더 간단한'LogDatabase' 서비스를'LogServices'로 전달하고 나머지'app' (LogServices'를 로깅을 위해 안전하게 사용할 수 있습니다)를 위해 현재'Database' 서비스를 사용하십시오. (나는 이것이 의미가 있기를 바랍니다 : P) – gkalpak

3

this answer 및 특히 Misko's blog을 참조하십시오. 거의 동일한 문제가 논의되는 의견의 Peter의 질문입니다. 해당 로그 데이터베이스를 원하는 곳

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

Misko의 대답은 (자바 코드를 사용하여)입니다 그래서 응용 프로그램에서, 당신은 당신의 응용 프로그램의 모든 부분에 대한

.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을 참조하십시오. 여기

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

과 내가 여기

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

injector을 사용하여 해결하기 위해 등장하는 코드입니다 오버라이드 (override) 할 수있는 링크입니다하려고 할 때