I have a menu in angular app and this menu controls the selected client in my web application.
As it is :
- My menu is a component which shares the selected client through a service.
- The selected client is shared as an Observable.
- The observable never complete. It just emit the new selected client when the menu is clicked.
- This is a replay subject. Each new subscriber retrieve the last emitted client.
it seemed like a good design but I encountered some problem when making new observables based on the client one (never completing observables). AFAIK this is due that the first observable never completesand this property will propagate.
//Command
export interface Command {
productName: string;
qty: number;
}
//The service
@Injectable()
export class ClientService {
private _client: ReplaySubject<Client> = new ReplaySubject(1);
setClient(client: Client) { // The menu component calls setClient on a user click
this._client.next(client);
}
getClient(): Observable<Client> { // getClient is heavilly called in child component to observe client selection events.
return this._client.asObservable();
}
}
getCommands(): Observable<Command> { //Used in a template with async pipe
//In a child component
const commandsObs = this.clientService.getClient()
//.take(1) //I am forced to use take(1) to get getCommands() observer to complete
.flatMap(c => {
return Observable.merge(getCommandsPromise1(c), getCommandsPromise2(c));
})
.reduce((acc, next) => Object.assign({}, acc, next))
.map(next => {
return finishMakingCommand(next));
})
.catch(err => /* Some error management code*/)
}
getCommandsPromise1(client: Client): Promise<any> {
//REST call returning a promise
return Promise.resolve({ 'command1': { 'productName': 'toy', qty: 1 } });
}
getCommandsPromise2(client: Client): Promise<any> {
//REST call returning a promise
return Promise.resolve({ 'command2': { 'productName': 'another toy', qty: 1 } });
}
finishMakingCommand(commands: any): Command[] {
// Flattens 'command1' and 'command2' to a list of commands
return [{'productName': 'toy', qty: 1}, {'productName': 'another toy', qty: 2}];
}
I'd like to know if more experienced developers think a never ending observable is a good design and what are the alternatives to avoid never ending observables.