Angular路由跳转导致消息组件无法接收解析数据问题
Angular组件间消息传递异常问题
补充说明
- 经测试确认,问题源于
file-upload.component.ts第54行的this.router.navigate(['view']);语句。移除该行后,直接在页面中嵌入ChatViewComponent而非通过router-outlet加载,应用即可正常运行。后续若找到路由内的解决方案会同步更新。
相关代码实现
FileUploadComponent 代码
import { Component, OnInit } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MessageParsingService } from '../services/message-parsing.service'; import { Router } from '@angular/router'; @Component({ selector: 'file-upload', templateUrl: './file-upload.component.html', styleUrls: ['./file-upload.component.scss'], }) export class FileUploadComponent implements OnInit { fileName = ''; constructor( private messageParsingService: MessageParsingService, private router: Router, public dialog: MatDialog ) {} ngOnInit(): void {} readFileContent(file: File): Promise<string> { return new Promise<string>((resolve) => { if (!file) { resolve(''); } const reader = new FileReader(); reader.onload = (e) => { const text = reader.result!.toString(); resolve(text); }; reader.readAsText(file); }); } async onFileSelected(event: any) { const file: File = event.target.files[0]; const fileReader = new FileReader(); if (file) { console.log(file.type + ' uploaded'); this.fileName = file.name; const formData = new FormData(); formData.append('thumbnail', file); const fileContent = await this.readFileContent(file); console.log(this.fileName); if (file.type == 'application/json') { this.messageParsingService.parseJson(fileContent); } this.router.navigate(['view']); } } }
MessageParsingService 代码
我编写了一个Angular服务MessageParsingService用于解析消息JSON文件,服务本身运行正常,它通过EventEmitter将解析后的消息发送至展示组件,但展示组件工作异常:
import { EventEmitter, Injectable } from '@angular/core'; import { Message } from '../models/message'; import { ParseEvent } from './parse-event'; @Injectable({ providedIn: 'root' }) export class MessageParsingService { public onParseComplete: EventEmitter<ParseEvent> = new EventEmitter<ParseEvent>(); public messages: Message[]; constructor() { this.messages = []; } public parseJson(jsonString: string) { let jsonObj = JSON.parse(jsonString); this.messages = jsonObj.chats[0].messages.map((item: { timestamp: any; fromMe: any; text: any; }) => { var msg = { timestamp: item.timestamp, fromMe: item.fromMe, text: item.text, } this.onParseComplete.emit(new ParseEvent(msg)); return msg; }); console.log("Messaged parsed by service: " , this.messages); } }
测试用JSON文件
{ "chats": [ { "contactName": "Test", "messages": [ { "timestamp": "2022-12-11T17:00:12Z", "id": "35A8984427489ACE786A9F5DFA81E7", "fromMe": true, "type": "text", "text": "Hello!" }, { "timestamp": "2022-12-11T21:34:04Z", "id": "009715FBED647B52CD4EA6AE9A7CA4", "fromMe": false, "type": "text", "text": "How are you?" }, { "timestamp": "2022-12-11T21:34:23Z", "id": "479AFD522FEC7444991CCA578EDF9F", "fromMe": false, "type": "text", "text": "What are you doing today?" } ] } ] }
ParseEvent 代码
import { Message } from "../models/message"; export class ParseEvent { message: Message; constructor(m: Message){ this.message = m; } }
ChatViewComponent 代码
import { Component, OnInit } from '@angular/core'; import { Message } from '../models/message'; import { MessageParsingService } from '../services/message-parsing.service'; import { ParseEvent } from '../services/parse-event'; @Component({ selector: 'app-chat-view', templateUrl: './chat-view.component.html', styleUrls: ['./chat-view.component.scss'] }) export class ChatViewComponent implements OnInit { private _serviceSubscription; messages: Message[]; constructor(private messageParsingService: MessageParsingService) { this.messages = []; this._serviceSubscription = this.messageParsingService.onParseComplete.subscribe({ next: (event: ParseEvent) => { console.log('Received message from parseEvent', event.message); this.messages.push(event.message); } }) } public logMessages(){ console.log("Log current messages: ", this.messages); } ngOnInit(): void { console.log('chat view component msgs: ', this.messages); } }
ChatViewComponent HTML 代码
<app-message *ngFor="let m of messages" [timestampInput]="m.timestamp" [fromMeInput]="m.fromMe" [textInput]="m.text" > </app-message> <button mat-raised-button (click)="logMessages()">Log current messages</button>
问题核心
我在ChatViewComponent中订阅了解析服务的EventEmitter,每次事件触发时都会把消息推到组件的messages数组里——控制台日志明明显示消息已经成功接收,但在subscribe块外访问这个数组时,不管是点击logMessages()按钮,还是在HTML模板里用*ngFor渲染,数组始终是空的。
我尝试过用BehaviorSubject和Observable替换EventEmitter,结果还是一样;也把数组改成any类型排查对象格式问题,完全没有效果。

内容的提问来源于stack exchange,提问作者paulf
相关产品推荐
相关产品推荐

