2014-04-07 26 views
12

मैं अनुक्रमित डीबी डेटाबेस में त्रुटियों को सहेजकर (या सक्षम होने पर डीबग) को कोणीय की $ लॉग सेवा का विस्तार करने के लिए एक लॉगर सेवा बना रहा हूं। यहां कोड है:कोणीय जेएस परिपत्र निर्भरता

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- निर्भरता/ 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

खतरनाक बात यह है कि एक अनंत लूप में प्रवेश करना है जो आपके ऐप को कुचल देगा (यही वह है जो कोणीय आपको पहले स्थान से बचाने की कोशिश कर रहा है)। यदि आप इसे क्रिया में देखना चाहते हैं, तो मेरे डेमो पर जाएं और लाइन 'service1.serve() पंक्ति को अपूर्ण करें;' "कोणीय" तरीका परिपत्र निर्भरताएं नहीं बनाना है (और इस मामले में मुझे लगता है कि आप नहीं कर सकते, क्योंकि आप 'लॉग सेवा' प्रदान करने के लिए 'डेटाबेस' की आवश्यकता है और आप 'डेटाबेस' में उपलब्ध 'लॉग सर्विसेज' भी प्राप्त करना चाहते हैं (जो स्वयं में एक विरोधाभास है :))। – gkalpak

+1

यदि आप "इसे सुरक्षित खेलना चाहते हैं", तो मुझे 2 विकल्प दिखाई देते हैं: 1.) 'डेटाबेस' के लिए एक सरल लॉगिंग तंत्र का उपयोग करें (जो 'डेटाबेस' पर निर्भर नहीं है)। 2.) 'लॉग सेवा' के लिए और बाकी ऐप के लिए समान 'डेटाबेस' सेवा का उपयोग न करें। 'लॉग सर्विसेज' पर जाने के लिए एक सरल 'लॉगडेटाबेस' सेवा (जो 'लॉग सर्विसेज' पर निर्भर नहीं है) का उपयोग करें और अपने शेष ऐप के लिए अपनी वर्तमान 'डेटाबेस' सेवा का उपयोग करें (जो लॉगिंग के लिए सुरक्षित रूप से 'लॉग सर्विसेज' का उपयोग कर सकते हैं)। (मुझे उम्मीद है कि यह समझ में आता है: पी) – gkalpak

3

this answer और विशेष रूप से Misko's blog और विशेष रूप से टिप्पणियों में पीटर का प्रश्न, जिसमें लगभग एक ही समस्या पर चर्चा की गई है।

Misko के जवाब (जावा कोड का उपयोग) है

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 या $ संसाधन या कुछ के लिए एक रैपर है? यदि ऐसा है, तो मैं अपने सिस्टम में विशेषज्ञ सिस्टम से सहमत हूं) विकल्प: लॉगिंग त्रुटियों के लिए $ http का उपयोग न करें क्योंकि अगर त्रुटि $ http को मार देती है तो क्या होगा? इसके बजाय XMLHTTPRequest का उपयोग करें। कुछ चर्चाओं के लिए here देखें।

0

मैं जब ओवरराइड करने के लिए 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

उम्मीद है कि यह आपको

संबंधित मुद्दे