You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 23:50:27