Within my Angular 5 app, I have implemented a unique approach to connecting components and services. This is achieved through a 'broker' object which utilizes RXJS Subject fields to facilitate communication and command execution within the system. However, because there are no components directly injecting these services, they remain uncalled and undeclared.
To work around this issue, I have employed the use of the useValue
field in the following manner:
import { NgModule } from '@angular/core';
import { DataBroker } from './brokers/data.broker';
import { SystemBroker } from './brokers/system.broker';
import { NotificationBroker } from './brokers/notification.broker';
import { LoggerService } from './services/logger.service';
import { SocketService } from './services/socket.service';
import { DataService } from './services/data.service';
import { SystemService } from './services/system.service';
// Instantiating necessary objects
const systemBroker: SystemBroker = new SystemBroker();
const dataBroker: DataBroker = new DataBroker();
const notificationBroker: NotificationBroker = new NotificationBroker();
const loggerService: LoggerService = new LoggerService(systemBroker);
const socketService: SocketService = new SocketService(loggerService, systemBroker, notificationBroker);
const dataService: DataService = new DataService(loggerService, socketService, dataBroker);
const systemService: SystemService = new SystemService(loggerService, socketService, systemBroker);
@NgModule({
providers: [
{ provide: SystemBroker, useValue: systemBroker },
{ provide: DataBroker, useValue: dataBroker },
{ provide: NotificationBroker, useValue: notificationBroker },
{ provide: LoggerService, useValue: loggerService },
{ provide: SocketService, useValue: socketService },
{ provide: DataService, useValue: dataService },
{ provide: SystemService useValue: systemService },
]
})
export class AppServicesModule {
constructor() { }
}
This method successfully creates instances; however, it presents another challenge where data passed through these services via the broker does not trigger change detection.
As an example, here is how data is transmitted through the broker using a snippet of code (this works correctly with the current workaround):
...
@Injectable()
export class DataService {
constructor(dataBroker: DataBroker, socketService: SocketService) {
socketService.on('NETWORK_CONFIG', (value: NetworkConfiguration) =>
dataBroker.networkConfiguration.status.next(value));
}
}
If I were to provide these objects in the typical way:
import { NgModule } from '@angular/core';
import { DataBroker } from './brokers/data.broker';
import { SystemBroker } from './brokers/system.broker';
import { NotificationBroker } from './brokers/notification.broker';
import { LoggerService } from './services/logger.service';
import { SocketService } from './services/socket.service';
import { DataService } from './services/data.service';
import { SystemService } from './services/system.service';
@NgModule({
providers: [
SystemBroker,
DataBroker,
NotificationBroker,
LoggerService,
SocketService,
DataService,
SystemService
]
})
export class AppServicesModule {
constructor(systemBroker: SystemBroker
dataBroker: DataBroker,
notificationBroker: NotificationBroker,
loggerService: LoggerService,
socketService: SocketService,
dataService: DataService,
systemService: SystemService) { }
}
Everything functions as expected. While my current workaround suffices, I am interested in understanding the intended use case for the useValue
if it behaves differently in this scenario. It may seem trivial, but finding the correct approach would be beneficial.
Anticipating the question, "why not simply use the services directly?" Our team frequently employs the broker pattern to seamlessly swap out service implementations without requiring modifications to our components.