Issue
I don't understand why *ngFor make infinite loop when I use function to return value.
I use Angular 8
Chat View HTML Template
<div class="row conpeek_message_chat_row" *ngFor="let chatMessage of chatMessages | async ">
<div class="conpeek_chat_message_inner [innerHTML]="getChatMessageText(chatMessage)"></div>
</div>
Chat View Component
private chatMessages:Observable<Array<any>>;
ngAfterViewInit() {
this.chatMessages = this.chatMessagesService.getMessages();
}
getChatMessageText(chatMessage) {
if (chatMessage.type == 'text' || chatMessage.type == 'info') {
console.log('TYPE TEXT');
return chatMessage.value;
}
if (chatMessage.type == 'image') {
let img_obj = `<div class="conpeek_msg_img_outer"><img src="${chatMessage.value}"></div>`;
return img_obj;
}
if (chatMessage.type == 'file') {
let file_obj = `<a>${chatMessage.filename}</a>`;
return file_obj;
}
}
Chat Messages Service
private chatMessages = [];
private chatMessagesStream = new BehaviorSubject(this.chatMessages);
constructor(private dialogInfoService: DialogInfoService) {
this.dialogInfoService.getDialogMembers().subscribe(members => {
this.dialogMembers = members;
});
}
getMessages(): Observable<any> {
return this.chatMessagesStream.asObservable();
}
addMessage(chatMessage) {
if (chatMessage.type != 'info') {
for (let member of this.dialogMembers) {
if (member.member_uuid == chatMessage.sender_dialog_uuid) {
chatMessage.sender_name = member.member_presentation_name;
chatMessage.avatar_id = member.avatar_id;
if (member.member_uuid == this.dialogInfoService.getOwnDialogUUID()) {
chatMessage.sender_type = 'contact';
chatMessage.status = 'sending';
} else {
chatMessage.sender_type = 'consultant';
}
}
}
}
this.chatMessages.push(chatMessage);
this.chatMessagesStream.next(this.chatMessages);
}
After init this component and receive first message, I get infinite loop of messages console.log('TYPE TEXT');
in console
When I use it to make request for an image message type to download a blob, my chrome browser is crashing.
Why is it happening, and how to fix it?
EDITED I found the clue why I have "infinite" loop over here. I recreate the app with minimum additional code and all works almost good. But when I added WebSocket to my app, and when this webscoket make some action (open connection, send message, close connection etc.) my loop make iteration. The infinite loop is just a ping-pong messages which my websocket do with server to detect connections problems vert quickly.
Here I show the problem, check console logs after every action WS makes, or send ws msg by click the button.
I read something about it, and every change detection event like button click, http request or websocket action cause this loop iteration.
https://stackblitz.com/edit/angular-xpb5hw
Solution
I resolved the problem by putting *ngFor
part of code to new component and add to this component decorator changeDetection: ChangeDetectionStrategy.OnPush
option.
On init have function to stop detect changes (detach()
). Loop iterate now only when new messages from service comes (I added detachChanges in subcribe fn as below).
I need to isolate this component because in Angular every button click, request or WebSocket message trigers a Detection Change in whole application, now I controll this.
ChatMessagesViewComponent
@Component({
selector: 'chat-messages-view',
template: `... *ngFor html here only ...`,
styleUrls: ['./chat-messages-view.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
constructor(private chatMessagesService: ChatMessagesService, private cd: ChangeDetectorRef) {
}
ngOnInit() {
this.chatMessages = this.chatMessagesService.getMessages();
this.cd.detach();
}
ngAfterViewInit() {
this.chatMessagesService.getMessages().subscribe(messages => {
this.cd.detectChanges();
this.scrollMessagesToBottom(true);
});
this.scrollMessagesToBottom(false);
}
Answered By - Patryk
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.