2
votes

I have a messages Observable which I use to display notifications on the page. The issue I'm having is when an error occurs on page load before the messages Component has been initialised means the Observable hasn't been subscribed to and therefore is undefined when I try to emit the error.

export class MessageService {
    public messagesSource: Observable<IMessage>;
    private messagesObserver: any;

    constructor() {
        console.log('MessageService constructor called');
        this.messagesSource = new Observable(observer => {
            console.log('MessageService observer called');
            this.messagesObserver = observer;
        }).share();
    }

    public show = (message: IMessage) => {
        if (this.messagesObserver) {
            this.messagesObserver.next(message);
        } else {
            console.error('this.messagesObserver is not initialised', this.messagesObserver);
        }
    }
}


export class MessagingComponent {
    public messages: IMessage[] = [];

    constructor(private messageService: MessageService) {
        console.log('messaging component constructor');
        this.messageService.messagesSource.subscribe(message => this.setMessage(message));
    }
}

// and within my HttpService:
private errorHandler = (error: Response): Observable<any> => {
    const err: string = error.text() || JSON.stringify(error);
    console.error('App error occurred:', err);
    this.messageService.show({ content: err, level: 'danger'});
    return Observable.from([null]);
}

Normal operation log:

Navigated to http://localhost:8090/

MessageService constructor called

messaging component constructor

MessageService observer called

Angular is running in the development mode.

And when there is an error in a resolver:

Navigated to http://localhost:8090/jobs

MessageService constructor called

GET http://localhost:7777/api/jobs 401 (Unauthorized)

App error occurred: Authorization failure, invalid bearer token.

this.messagesObserver is not initialised undefined

messaging component constructor

MessageService observer called

Angular is running in the development mode.

So I need a way to have new Observable(observer) to immediately create the Observer so that it isn't undefined and the messages aren't lost and emitted when the component is ready to subscribe.

1
Maybe you're looking for ReplaySubject? github.com/Reactive-Extensions/RxJS/blob/master/doc/api/… - Adnan A.

1 Answers

2
votes

you need to create a BehaviorSubject,

Observers can subscribe to the subject to receive the last (or initial) value and all subsequent notifications.

You may also use ReplaySubject, if you want to buffer all the responses.

Hope this helps!!