Should we avoid circular dependencies?

Asked

Viewed 407 times

1

When working with Angularjs it is very common to have applications where services contain only HTTP calls to the server that will store the data. However, in an application where we will not have a server our service may be responsible for many business logic (do not worry about the code being visible to the user) and because of this one service may call another and vice versa (this is bad practice).

Imagine the following situation:

angular.module('app').service('logAPI',[ function('fileManager') {

    var _logList = [];

    var LogMessage = function(system, type, message, value, now) {
        this.system = system;
        this.type = type;
        this.message = message;
        this.value = value;
        this.time = now;
    };

    this.scheduleLogMessage = function(system, type, message, value) {
        if (_logList.length < 300) {
            var now = utilAPI.getFormattedTime();
            var log = new LogMessage(system, type, message, value);
            _logList.push(log);
        }
    };

    this.processLog = function() {
        if (_logList.length >= 200) {
            fileManager.upload(_logList[0]);
        }
    };  

}])

.service('fileManager',[ function('storageAPI') {

    var upload = function(obj) {
        storageAPI.upload(obj).then(function success() {
            logAPI.scheduleLogMessage('a', 'a', 'a', 'a');
        }, function error() {
            logAPI.scheduleLogMessage('a', 'a', 'a', 'a');
        })
    }

}])

.controller('appCtrl', ['', function('logAPI'){


    while(true) {
        logAPI.processLog();
    }

}]);

The Angularjs will accuse of circular dependency. Are there ways to circumvent this and the angular 'ignore' this dependency, however, this is bad practice ? We must avoid?

Editing: Improvement of the example

Man logAPI is responsible for managing every log generated by the system and after an X amount of message, it starts uploading those logs. When the upload is done, it can also log in to record what happened. In general, everything in my system generates LOG and because of that, I can’t think of a way to break this dependency.

1 answer

2


The best way I know of avoiding circular reference, is to create a separate module, where are the business rules that are common to one or more services. Not just leading to the world of Angular.
On the blog of Misko Hevery, one of the authors of the angular, he quotes exactly that.

Follow the link for consultation: Blog

Editing:

The idea of a logger is that it is like a container of logs and he is responsible for logging in everything. Already his fileManager have to give answers to what he did and not log in.

Therefore, we can use Promises within the fileManager and return a reply to logApi, who is responsible for logging in.

The structure below is more or less a sketch of what we want. (Excuse me the drawing, I had to do in Paint)

Diagrama

And here follows a Jsfiddle with an example for you to base. When you click on the "LOG" button in the example, open the browser console

I hope it helps you

  • Based on my opinion on circular reference, I went searching and on an American stackoveflow link was where I found Misko Hevery’s blog. I found it very valid to put here.

  • I made the edits based on what you changed.

  • I think your solution will work for me, but I have some questions. 1. How you access {{vm.result}} where in your controller you have no $Scope.vm.result, 2. What you return from Filemanager is a precedent?

    1. In the Maincontroller function, I assign a variable self, that represents the controller. This makes me avoid having to access the $scope. It’s actually a technique of Binding, which, in other programming languages, is implicit. You have more information about this here: http://alistapart.com/article/getoutbindingsituations 2. Yes
  • I will test here, I liked the solution. Thanks for the help!

  • Arrange! We’re all here for this. Hug

  • Can you return a file from an http call? like, there you returned a call from a function there, but instead of Promise, I had to still do an http.get, how would it look? I tried to test here but did not roll, https://jsfiddle.net/4awmh27d/2/

  • 1

    Yes, in case you should return own $http.get, which is already a Promise, see the example http://jsfiddle.net/4awmh27d/3/

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.