web-dev-qa-db-fra.com

Dépendance circulaire AngularJS

Je crée un service de journalisation pour étendre le service $ log de angular en enregistrant les erreurs (ou le débogage, le cas échéant) dans une base de données indexedDB. Voici le code:

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

    // ...
})

Cela fonctionne dans mes services comme prévu. Maintenant, le problème est que je ne peux pas utiliser mon enregistreur dans le service de base de données, car il génère une erreur de dépendance circulaire. Je comprends le problème mais je ne sais pas comment je devrais le résoudre ... Comment devrais-je résoudre ce problème?

Merci pour ton aide :-)

12
ImSoNuts

La raison pour laquelleAngular se plaint d'une dépendance circulaire est que ... eh bien, il y en a une.
C'est un chemin très dangereux, mais si vous savez ce que vous faites (derniers mots célèbres), il existe une solution pour contourner ce problème:

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

    // ...
})

Voir aussi cette courte démo.

29
gkalpak

Voir cette réponse et en particulier le blog de Misko et en particulier la question de Peter dans les commentaires, dans laquelle presque le même problème est discuté.

La réponse de Misko est (en utilisant du code Java)

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

Donc, dans votre application, vous avez

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

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

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

Utilisez LoggingDB pour chaque partie de votre application où vous souhaitez une base de données qui se connecte. (Ou est-ce un enregistreur qui utilise la base de données!)

Une autre pensée

Comment se fait-il que vous ayez une base de données sur le navigateur? Est-ce que Database est un wrapper pour $ http ou $ resource ou quelque chose comme ça? Si tel est le cas, je suis d’accord avec ExpertSystem dans son option 2): n’utilisez pas $ http pour les erreurs de journalisation, car si l’erreur tue $ http? Utilisez XMLHTTPRequest à la place. Voir ici pour une discussion.

3
poshest

J'ai fait face à ce problème en essayant de remplacer exceptionHandler 

voici le code où le problème est apparu 

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

et pour y remédier j'ai utilisé 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');
        //............
    }

voici un lien pour plus d'informations L'injection de résultats $ http dans une dépendance circulaire

espérons que cela vous aide

0
Basheer AL-MOMANI