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

Angular 4中如何等待所有异步HTTP请求完成后返回数据?

解决Angular服务中HTTP请求完成后返回卡片数据的问题

你的核心问题在于HTTP请求是异步操作,当前代码里getData()直接返回了初始数组,这时候请求还没完成,_cardMeter和_cardConsumption都是未赋值状态;而把return放进subscribe里会导致方法返回void,和组件期望的数组类型不匹配。下面是修正后的完整方案:

修改后的cards.service.ts

import {Injectable} from '@angular/core';
import {BaThemeConfigProvider, colorHelper} from '../../../theme';
import { Http, Headers, Response } from '@angular/http';
import {Observable} from "rxjs/Observable";
import 'rxjs/add/observable/forkJoin';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class CardsService {
  _meterCountURL = 'http://localhost:8080/meter/count';

  constructor(private _baConfig: BaThemeConfigProvider, private http: Http) { }

  getData(): Observable<any[]> {
    let pieColor = this._baConfig.get().colors.custom.dashboardPieChart;
    let headers = new Headers({
      'Content-type': 'application/x-www-form-urlencoded',
      'Authorization': 'Bearer ' + localStorage.getItem('id_token')
    });

    // 并行发起两个HTTP请求,等所有请求完成后再处理结果
    return Observable.forkJoin(
      this.http.get(this._meterCountURL, {headers: headers}).map(res => res.json()['data']),
      this.http.get(this._meterCountURL, {headers: headers}).map(res => res.json()['data'])
    ).map(([meterData, consumptionData]) => {
      // 请求完成后,组装成组件需要的卡片格式
      return [
        {
          color: pieColor,
          description: 'Consumo do mês atual',
          stats: consumptionData || 0,
          icon: 'ion-flash',
        },
        {
          color: pieColor,
          description: 'Número de unidades ativas',
          stats: meterData || 0,
          icon: 'ion-ios-speedometer',
        }
      ];
    }).catch(error => {
      console.error('卡片数据请求失败:', error);
      return Observable.throw(error);
    });
  }
}

修改后的cards.component.ts

import {Component, OnInit} from '@angular/core';
import {CardsService} from './cards.service';
import 'easy-pie-chart/dist/jquery.easypiechart.js';

@Component({
  selector: 'cards',
  templateUrl: './cards.html',
  styleUrls: ['./cards.scss']
})
// TODO: move easypiechart to component
export class Cards implements OnInit {
  public charts: any[];

  constructor(private _cardsService: CardsService) { }

  ngOnInit() {
    // 在组件初始化钩子中订阅数据,确保请求完成后再赋值
    this._cardsService.getData().subscribe(
      cardData => {
        this.charts = cardData;
        // 数据加载完成后再初始化图表,避免空数据问题
        this.initEasyPieChart();
      },
      error => {
        console.error('加载卡片数据出错:', error);
      }
    );
  }

  private initEasyPieChart() {
    // 这里放easy-pie-chart的初始化逻辑
    // 示例: $('.easy-pie-chart').easyPieChart({/* 配置项 */});
  }
}

关键修改说明:

  1. 服务端调整:

    • 让getData()返回Observable<any[]>,不再直接返回数组,把数据组装逻辑放到forkJoin的map操作符中,确保只有当所有请求完成后才生成最终的卡片数据。
    • 移除了服务中多余的状态变量_cardMeter和_cardConsumption,直接通过forkJoin的返回值处理数据。
    • 补充了RxJS操作符的导入,避免出现操作符找不到的错误。
    • 添加了错误捕获逻辑,方便排查请求问题。
  2. 组件端调整:

    • 实现OnInit生命周期钩子,在ngOnInit中订阅服务数据,避免在构造函数中处理异步操作(构造函数只适合依赖注入)。
    • 把图表初始化逻辑放到initEasyPieChart()方法中,确保在数据加载完成后再执行,避免DOM操作时数据未就绪的问题。

这样修改后,就能保证所有HTTP请求完成后再返回卡片数据,解决[object Object]显示异常和类型不匹配的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:19:17