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

切换路由后Angular调用MongoDB API获取数据出现undefined问题

Angular路由切换后数据变为undefined的问题分析与解决

我创建了一个从MongoDB API获取数据的Angular服务,首次运行时一切正常,但切换到其他路由后再返回,数据变为undefined,刷新浏览器后恢复正常。相关代码如下:

相关代码

product.service.ts

import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, catchError, retry, throwError, map } from 'rxjs';
import { Product } from '../interface/product';

@Injectable({
    providedIn: 'root'
})
export class productAPIService {

    constructor(private _http: HttpClient) { }

    getProducts(category: string): Observable<any> {
        const headers = new HttpHeaders().set("Content-Type", "text/plain;charset=utf-8")
        const requestOptions: Object = {
            headers: headers,
            responseType: "text"
        }
        return this._http.get<any>("http://localhost:3002/" + category, requestOptions).pipe(
            map(res => JSON.parse(res) as Array<Product>),
            retry(3),
            catchError(this.handleError)
        )
    }
    
    track_products(category: string){
        let products_lst: any;
        this.getProducts(category).subscribe(res => {
            products_lst = res;
        });
        return products_lst;
    }

    handleError(error: HttpErrorResponse) {
        return throwError(() => new Error(error.message))
    }
}

product-list.component.ts

import { CommonModule } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { productAPIService } from '../../services/product.service';
import {NgxPaginationModule} from 'ngx-pagination';

@Component({
  selector: 'app-product-list',
  standalone: true,
  imports: [CommonModule, NgxPaginationModule],
  templateUrl: './product-list.component.html',
  styleUrl: './product-list.component.css'
})
export class ProductListComponent implements OnInit, OnDestroy{
  p: number = 1;
  all_products: any = [];
  daychuyen_products: any = [];
  nhan_products: any = [];
  vongtay_products: any = [];
  bongtai_products: any = [];
  fil_products: any = [];

  constructor(private _service: productAPIService) { }

  ngOnInit(): void {
    this.daychuyen_products = this._service.track_products("daychuyen");
    this.nhan_products = this._service.track_products("nhan");
    this.vongtay_products = this._service.track_products("vongtay");
    this.bongtai_products = this._service.track_products("bongtai");

    this.all_products = [].concat(this.bongtai_products, this.nhan_products, this. vongtay_products, this.daychuyen_products).sort(() => Math.random() - 0.5);
    this.fil_products = this.all_products;
    console.log(this.fil_products);
  }

  filledStars(num: number) {
    return Array(num).fill(0).map((x, i) => i + 1);
  }
  ngOnDestroy(): void {}
}

问题原因

  1. 异步逻辑处理错误:track_products方法中,你在订阅Observable后立刻返回products_lst,此时HTTP请求还未完成,products_lst仍为初始的undefined。首次运行时可能因浏览器缓存或请求速度快,组件初始化时刚好拿到数据;但路由切换后组件重新初始化,请求未完成就赋值,导致数据为undefined。
  2. 组件数据拼接时机错误:ngOnInit中直接用track_products的返回值拼接数组,此时异步请求未完成,拼接的是undefined,最终导致all_products和fil_products数据异常。

解决方案

1. 修改服务层,移除错误的同步封装

删掉track_products方法,直接暴露返回Observable的getProducts,让组件处理异步逻辑:

import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, catchError, retry, throwError, map } from 'rxjs';
import { Product } from '../interface/product';

@Injectable({
    providedIn: 'root'
})
export class productAPIService {

    constructor(private _http: HttpClient) { }

    getProducts(category: string): Observable<Product[]> {
        const headers = new HttpHeaders().set("Content-Type", "text/plain;charset=utf-8")
        const requestOptions: Object = {
            headers: headers,
            responseType: "text"
        }
        return this._http.get<any>("http://localhost:3002/" + category, requestOptions).pipe(
            map(res => JSON.parse(res) as Product[]),
            retry(3),
            catchError(this.handleError)
        )
    }

    handleError(error: HttpErrorResponse) {
        return throwError(() => new Error(error.message))
    }
}

2. 组件中正确处理异步请求

使用forkJoin同时发起多个请求,等待所有请求完成后再处理数据:

import { CommonModule } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { productAPIService } from '../../services/product.service';
import {NgxPaginationModule} from 'ngx-pagination';
import { forkJoin } from 'rxjs';

@Component({
  selector: 'app-product-list',
  standalone: true,
  imports: [CommonModule, NgxPaginationModule],
  templateUrl: './product-list.component.html',
  styleUrl: './product-list.component.css'
})
export class ProductListComponent implements OnInit, OnDestroy{
  p: number = 1;
  all_products: any = [];
  daychuyen_products: any = [];
  nhan_products: any = [];
  vongtay_products: any = [];
  bongtai_products: any = [];
  fil_products: any = [];
  isLoading: boolean = true; // 可选:添加加载状态

  constructor(private _service: productAPIService) { }

  ngOnInit(): void {
    // 同时发起多个分类请求,等待全部完成
    forkJoin([
      this._service.getProducts("daychuyen"),
      this._service.getProducts("nhan"),
      this._service.getProducts("vongtay"),
      this._service.getProducts("bongtai")
    ]).subscribe(([daychuyen, nhan, vongtay, bongtai]) => {
      this.daychuyen_products = daychuyen;
      this.nhan_products = nhan;
      this.vongtay_products = vongtay;
      this.bongtai_products = bongtai;

      // 所有数据获取完成后再拼接排序
      this.all_products = [].concat(bongtai, nhan, vongtay, daychuyen).sort(() => Math.random() - 0.5);
      this.fil_products = this.all_products;
      this.isLoading = false;
      console.log(this.fil_products);
    });
  }

  filledStars(num: number) {
    return Array(num).fill(0).map((x, i) => i + 1);
  }
  ngOnDestroy(): void {}
}

3. 可选:添加加载状态提升体验

在组件模板中添加加载提示:

<div *ngIf="isLoading">加载中...</div>
<div *ngIf="!isLoading">
  <!-- 商品列表渲染内容 -->
</div>

内容的提问来源于stack exchange,提问作者Curt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 03:05:20