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

Angular中API请求完成前避免显示404组件的解决方案

Angular组件等待API加载完成再渲染视图的解决方案

问题根源

当前代码中,组件初始化时salesData默认是undefined,API请求需要1秒才能返回数据,这会直接触发@else分支显示app-not-found组件。核心问题是没有区分「数据正在加载」和「无数据/请求失败」两种状态。

解决方案

方法1:新增加载状态标记(最直接的修改)

在组件中添加一个加载状态变量,用来控制加载过程中的显示逻辑,避免过早渲染错误组件。

修改业务逻辑代码:

isLoading = true; // 新增加载状态标记

getAds(n:string) {
   this.isLoading = true; // 请求开始时标记为加载中
   const request$ = n.includes("sales") ? this.service.getAds() : this.service.getRentsAds();

   request$.subscribe({
      next: (response) => {
        this.salesData = response;
        this.records = this.salesData.length;
        this.pageRecords = this.salesData.slice(0, this.recordsPerPage);
        this.totalPages = this.records / this.recordsPerPage;
  
        // 替代原for循环,更简洁的分页数组生成方式
        this.numberOfPages = Array.from({length: Math.ceil(this.totalPages)}, (_, i) => i + 1);
      },
      complete: () => {
        this.isLoading = false; // 请求完成(无论成功失败)取消加载状态
      },
      error: () => {
        this.isLoading = false; // 请求失败也要取消加载状态
        // 可在此添加错误提示逻辑,比如设置errorStatus变量
      }
   });
}

修改组件模板:

<!-- 加载中显示占位内容,比如骨架屏或加载动画 -->
@if(isLoading) {
  <div class="flex justify-center items-center h-96">
    <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-500"></div>
  </div>
} @else if(salesData) {
  <!-- 原有的数据渲染内容 -->
  <div class="flex flex-col space-y-4 max-w-md mx-auto bg-white shadow-md overflow-hidden md:max-w-6xl">
    @for (i of pageRecords; track i.id) {
      <!-- 每条数据的渲染代码 -->
    } 
  </div>

  @if (totalPages > 0) {
    <!-- 分页组件代码 -->
  }
} @else {
  <!-- 仅当请求完成且无数据时,才显示错误组件 -->
  <app-not-found />
}

方法2:使用AsyncPipe(RxJS最佳实践)

通过将API请求转为Observable,配合Angular的AsyncPipe自动处理订阅和状态,无需手动管理加载状态和订阅取消。

修改业务逻辑代码:

salesData$!: Observable<any[]>; // 定义Observable变量

getAds(n:string) {
   this.salesData$ = n.includes("sales") ? this.service.getAds() : this.service.getRentsAds();
   // 在管道中处理分页逻辑,简化组件代码
   this.salesData$ = this.salesData$.pipe(
      tap(response => {
        this.records = response.length;
        this.pageRecords = response.slice(0, this.recordsPerPage);
        this.totalPages = this.records / this.recordsPerPage;
        this.numberOfPages = Array.from({length: Math.ceil(this.totalPages)}, (_, i) => i + 1);
      })
   );
}

修改组件模板:

<!-- AsyncPipe会自动等待Observable发出数据,数据未返回前不会进入else分支 -->
@if (salesData$ | async; as salesData) {
  <!-- 原有的数据渲染内容 -->
  <div class="flex flex-col space-y-4 max-w-md mx-auto bg-white shadow-md overflow-hidden md:max-w-6xl">
    @for (i of pageRecords; track i.id) {
      <!-- 每条数据的渲染代码 -->
    } 
  </div>

  @if (totalPages > 0) {
    <!-- 分页组件代码 -->
  }
} @else {
  <!-- 数据加载中显示的内容 -->
  <div class="flex justify-center items-center h-96">
    <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-500"></div>
  </div>
}

方法3:使用路由Resolve守卫(预加载数据)

如果希望进入组件前就完成数据加载,可以使用Angular的路由Resolve守卫,确保组件激活时数据已经准备就绪。

1. 创建Resolve守卫:

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { YourService } from './your.service';

@Injectable({ providedIn: 'root' })
export class AdsResolver implements Resolve<any[]> {
  constructor(private service: YourService) {}

  resolve(route: ActivatedRouteSnapshot): Observable<any[]> {
    const type = route.paramMap.get('type') || 'sales'; // 从路由参数获取数据类型
    return type.includes('sales') ? this.service.getAds() : this.service.getRentsAds();
  }
}

2. 配置路由:

const routes: Routes = [
  {
    path: 'ads/:type',
    component: YourComponent,
    resolve: { salesData: AdsResolver } // 指定Resolve守卫
  }
];

3. 在组件中获取预加载的数据:

import { ActivatedRoute } from '@angular/router';

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  this.salesData = this.route.snapshot.data['salesData'];
  // 处理分页逻辑...
}

这种方式下,组件初始化时已经有数据,不会出现加载过程中的错误组件显示。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 21:37:34