Круговая зависимость AngularJS

Я делаю службу регистрации, чтобы расширить службу журнала angular $, путем сохранения ошибок (или отладки, если они включены) в базу данных indexedDB. Здесь код:

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

Причина 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);
        }
    };

    // ...
})

См. также эту короткую демонстрацию.

Ответ 2

См. этот ответ и, в частности, Misko blog и, в частности, вопрос Питера в комментариях, в которых обсуждается почти одна и та же проблема.

Ответ 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. См. здесь для обсуждения.

Ответ 3

Я столкнулся с этой проблемой при попытке переопределить 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');
        //............
    }

вот ссылка для дополнительной информации Ввод $http приводит к циклической зависимости

надеюсь, что это поможет вам