I have a service (MessageService) that emits some messages based on some other app events.
Then, I have a component MessagesComponent and I'd like to render all the messages that were emitted by my Service. My approach is to use an Observable<Message[]> to store and reactively update the UI every time a new Message arrives.
Here's my working solution
@Component({
selector: 'app-messages',
template: `
<h2>Received messages</h2>
<ol>
<li class="message" *ngFor="let message of messages$ | async">
{{ message }}
</li>
</ol>
`,
styles: [``]
})
export class MessagesComponent implements OnInit, OnDestroy {
destroy$ = new Subject<void>();
messages$ = new BehaviorSubject<Message[]>([]);
constructor(private messagesService: MessagesService) {}
ngOnInit(): void {
this.messagesService.message$
.pipe(
takeUntil(this.destroy$),
switchMap((message: Message) =>
this.messages$.pipe(
take(1),
map((all: Message[]) => {
return [...all, message];
})
)
)
)
.subscribe((messages: Message[]) => {
this.messages$.next(messages);
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}
现在,我从一个空的BehaviorSubject数组开始存储所有消息.然后,在ngOnInit钩子中,我订阅了MessagesService's message$,在新的发布之后,我将把BehaviorSubject中的内容与新消息结合起来,从而发布一个包含所有项目的新array.
messages$: Observable<Message[]> = this.messagesService.message$.pipe(
switchMap((message: Message) =>
this.messages$.pipe(
startWith([]),
take(1),
map((all: Message[]) => [...all, message])
)
)
);
我试图使用数组本身作为他们自己使用SwitchMap+StartWith进行初始化的一部分,但它似乎不起作用,所以我在寻找一些其他 idea :)
哦,消息类型只是一个带有一些属性的简单接口.
export interface Message {
id: string;
value: string;
}