2014-04-07 17 views
12

Tôi đang tạo dịch vụ nhật ký, để mở rộng dịch vụ nhật ký $ của góc, bằng cách lưu các lỗi (hoặc gỡ lỗi nếu được bật) vào cơ sở dữ liệu được lập chỉ mụcDB. Đây là mã:AngularJS phụ thuộc tròn

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

    // ... 
}) 

Điều này làm việc trong các dịch vụ của tôi như dự định. Bây giờ vấn đề là tôi không thể sử dụng logger của tôi bên trong dịch vụ cơ sở dữ liệu, bởi vì nó ném một lỗi phụ thuộc vòng tròn. Tôi hiểu vấn đề nhưng tôi không biết làm sao tôi nên giải quyết nó ... Làm thế nào để tôi có được điều này?

Cảm ơn bạn đã trợ giúp :-)

+1

Vui lòng xem câu trả lời của tôi cho một câu hỏi tương tự: http://stackoverflow.com/questions/20647483/angularjs-injecting-service-into-a-http-interceptor-circular-dependency/ 21632161 # 21632161 –

Trả lời

28

Lý do Góc khiếu nại về phụ thuộc vòng tròn là ... cũng có một.
Đó là một con đường rất nguy hiểm để đi xuống, nhưng nếu bạn biết những gì bạn đang làm (lời cuối cùng nổi tiếng) sau đó là một giải pháp để phá vỡ rằng:

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

    // ... 
}) 

Xem, cũng, đây short demo.

+0

Cảm ơn bạn, nó đang hoạt động theo cách này. Bây giờ bạn nghĩ gì sẽ là con đường an toàn? Tại sao con đường này lại nguy hiểm? Bạn có thể xây dựng được không? Tôi rất muốn làm những điều theo góc cạnh, và nếu có thể không sử dụng hacks. Câu hỏi là, tôi có lựa chọn khác không? – ImSoNuts

+3

Điều nguy hiểm là đi vào một vòng lặp vô hạn sẽ đè bẹp ứng dụng của bạn (đó là những gì mà Angular đang cố gắng bảo vệ bạn ngay từ đầu). Nếu bạn muốn thấy rằng trong hành động, đi đến demo của tôi và bỏ ghi chú dòng 'service1.serve(); 'Cách" Góc "không phải là để tạo ra phụ thuộc vòng tròn (và trong trường hợp này tôi nghĩ rằng bạn không thể, bởi vì bạn cần 'Database' để cung cấp' LogServices' và bạn cũng muốn có 'LogServices' trong' Database' (đó là nghịch lý trong chính nó :)). – gkalpak

+1

Nếu bạn muốn "phát an toàn", tôi thấy 2 tùy chọn: 1.) Đối với 'Cơ sở dữ liệu ', hãy sử dụng cơ chế ghi nhật ký đơn giản hơn (không dựa vào' Cơ sở dữ liệu '). 2.) Không sử dụng cùng một dịch vụ 'Database' cho' LogServices' và cho phần còn lại của ứng dụng. Sử dụng dịch vụ 'LogDatabase' đơn giản hơn (không đúng trên 'LogServices') để chuyển tới' LogServices' và sử dụng dịch vụ 'Database' hiện tại của bạn cho phần còn lại của ứng dụng (có thể sử dụng an toàn' LogServices' để ghi nhật ký). (Tôi hy vọng điều này có ý nghĩa: P) – gkalpak

3

Xem this answer và cụ thể là Misko's blog và đặc biệt là câu hỏi của Peter trong nhận xét, trong đó hầu như cùng một vấn đề chính xác được thảo luận.

câu trả lời Misko được (sử dụng mã Java)

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

Vì vậy, trong ứng dụng của bạn, bạn có

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

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

.service('LoggingDB', function(Database, LogServices) {...}) 

Sử dụng LoggingDB cho mỗi phần của ứng dụng của bạn, nơi bạn muốn có một cơ sở dữ liệu bản ghi. (Hoặc là nó một logger có sử dụng cơ sở dữ liệu!)

Một nghĩ

Làm thế nào mà bạn có một cơ sở dữ liệu trên trình duyệt? Cơ sở dữ liệu có phải là trình bao bọc cho $ http hoặc $ tài nguyên hay gì đó không? Nếu trường hợp đó xảy ra, tôi đồng ý với tùy chọn ExpertSystem trong tùy chọn 2 của anh ấy: không sử dụng $ http cho lỗi ghi nhật ký vì điều gì xảy ra nếu lỗi đó giết chết $ http? Sử dụng XMLHTTPRequest để thay thế. Xem here để thảo luận.

0

tôi phải đối mặt với vấn đề này khi cố gắng ghi đè exceptionHandler

đây là mã nơi vấn đề xuất hiện

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

và để sửa chữa nó tôi đã sử dụng 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'); 
     //............ 
    } 

đây là một liên kết để biết thêm thông tin Injecting $http results in a Circular dependency

hy vọng điều này sẽ giúp bạn

Các vấn đề liên quan