Some time ago, I started to refactor my code of the main project, decoupling the business logic from controllers to services, according to guidelines. Everything went well, until I faced the problem of circular dependency (CD). I read some resources about this problem:
Unfortunately, for me it is not clear now, how can I solve the problem of CD for my project. Therefore, I prepared a small demo, which represents the core features of my project:
Short description of components:
- gridCtrl Does not contain any business logic, only triggers dataload and when the data is ready, show grid.
- gridMainService This is the main service, which contains object gridOptions. This object is a core object of grid, contains some api, initialized by framework, row data, columns headers and so on. From this service, I was planning to control all related grid stuff. Function loadGridOptions is triggerd by gridCtrl and waits until the row data and column definitions are loaded by corresponding services. Then, it initializes with this data gridOptions object.
- gridConfigService This is simple service, which used to load column definitions. No problem here.
- gridDataService This service used to load row data with function loadRowData. Another feature of this service: it simulates the live updates, coming from server ($interval function). Problem 1 here!
- gridSettingsService This service is used to apply some settings to the grid(for example, how the columns should be sorted). Problem 2 here!
Problem 1: I have a circular dependency between gridMainService and gridDataService. First gridMainService use gridDataService to load row data with function:
self.loadRowData = function () {
// implementation here
}
But then, gridDataService receives the updates from server and has to insert some rows into grid. So, it has to use gridMainService:
$interval(function () {
var rowToAdd = {
make: "VW " + index,
model: "Golf " + index,
price: 10000 * index
};
var newItems = [rowToAdd];
// here I need to get access to the gridMainService
var gridMainService = $injector.get('gridMainService');
gridMainService.gridOptions.api.addItems(newItems);
index++;
}, 500, 10);
So, here I faced first CD.
Problem 2: I have a circular dependency between gridMainService and gridSettingsService. First, gridMainService triggering, when the grid is initially loaded and then it sets up default settings by the following function:
self.onGridReady = function () {
$log.info("Grid is ready, apply default settings");
gridSettingsService.applyDefaults();
};
But, to make some changes, gridSettingsService need an access to the gridMainService and its object gridOptions in order to apply settings:
self.applyDefaults = function() {
var sort = [
{colId: 'make', sort: 'asc'}
];
var gridMainService = $injector.get('gridMainService');
gridMainService.gridOptions.api.setSortModel(sort);
};
Question: How can I solve these CD cases in proper way? Because, Miško Hevery Blog was quite short and good, but I have not managed to apply his strategy to my case.
And currently, I don't like an approach of manual injection a lot, because I will have to use it a lot and the code looks a little bit fuzzy.
Please note: I prepared only a demo of my big project. You can probably advice to put all code in gridDataService and ready. But, I already has a 500 LOC in this service, if I merge all services, it will be a ~1300 LOC nightmare.