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

Angular中如何展示API返回的JSON响应值?

问题描述

我正在用Angular对接之前开发的Django Rest API,API有个端点返回当前登录用户数量。浏览器控制台能看到JSON响应,但页面上无法正确展示数值——模板里的users_online变量只显示[object Promise]。

我的模板代码:

<div *ngIf="authService.isLoggedIn()" class="fa fa-user">{{ users_online }}</div>

原app.service.ts代码:

import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {environment} from "../environments/environment";
import {firstValueFrom} from "rxjs";

export interface UsersOnlineCounterResponse {
  users_online: number;
}

const headers = {
  'Authorization': 'Bearer ' + localStorage.getItem('access_token'),
}

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

  constructor(private http: HttpClient) { }

  async UsersOnlineCounter() {
    await firstValueFrom(this.http.get<UsersOnlineCounterResponse>(environment.backend + '/api/v1/users/online', {headers})).then(data => {
      return data.users_online;
    });
  }
}

原app.component.ts代码:

import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { AppService } from "./app.service";
import { AuthService } from "./auth/auth.service";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'example.com'
  users_online = this.appService.UsersOnlineCounter();
  constructor(private titleService: Title, public authService: AuthService, public appService: AppService) {
  }
  ngOnInit() {
    this.titleService.setTitle(this.title);
  }
}

解决方案

问题根源

  1. UsersOnlineCounter是异步方法,直接赋值给users_online会得到Promise对象而非实际数值;
  2. 服务中的异步方法没有正确返回结果;
  3. 组件中未在生命周期钩子中处理异步逻辑,而是直接初始化赋值。

方案1:修复异步方法并在组件中手动处理

1. 修正AppService方法

确保方法正确返回数值,同时动态获取token(避免token过期或更新后失效):

import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {environment} from "../environments/environment";
import {firstValueFrom} from "rxjs";

export interface UsersOnlineCounterResponse {
  users_online: number;
}

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

  constructor(private http: HttpClient) { }

  async getUsersOnlineCounter(): Promise<number> {
    // 每次请求动态获取token
    const headers = {
      'Authorization': 'Bearer ' + localStorage.getItem('access_token'),
    };
    const response = await firstValueFrom(
      this.http.get<UsersOnlineCounterResponse>(`${environment.backend}/api/v1/users/online`, {headers})
    );
    return response.users_online;
  }
}

2. 修正AppComponent逻辑

初始化默认值,在ngOnInit中调用异步方法赋值:

import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { AppService } from "./app.service";
import { AuthService } from "./auth/auth.service";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'example.com';
  users_online = 0; // 设置默认值

  constructor(
    private titleService: Title, 
    public authService: AuthService, 
    public appService: AppService
  ) {}

  async ngOnInit() {
    this.titleService.setTitle(this.title);
    // 仅登录状态下获取数据
    if (this.authService.isLoggedIn()) {
      this.users_online = await this.appService.getUsersOnlineCounter();
    }
  }
}

3. 可选:添加加载状态

模板中可以增加加载提示,优化用户体验:

<div *ngIf="authService.isLoggedIn()" class="fa fa-user">
  {{ users_online === 0 ? '加载中...' : users_online }}
</div>

方案2:使用Angular Async管道(更简洁)

如果不想手动处理异步逻辑,可以让服务返回Observable,通过Async管道自动订阅:

1. 修正AppService方法

import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {environment} from "../environments/environment";
import {Observable, map} from "rxjs";

export interface UsersOnlineCounterResponse {
  users_online: number;
}

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

  constructor(private http: HttpClient) { }

  getUsersOnlineCounter(): Observable<number> {
    const headers = {
      'Authorization': 'Bearer ' + localStorage.getItem('access_token'),
    };
    return this.http.get<UsersOnlineCounterResponse>(`${environment.backend}/api/v1/users/online`, {headers})
      .pipe(map(response => response.users_online));
  }
}

2. 修正AppComponent逻辑

import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { AppService } from "./app.service";
import { AuthService } from "./auth/auth.service";
import { Observable } from "rxjs";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'example.com';
  users_online$: Observable<number>; // 用$后缀标识Observable

  constructor(
    private titleService: Title, 
    public authService: AuthService, 
    public appService: AppService
  ) {}

  ngOnInit() {
    this.titleService.setTitle(this.title);
    this.users_online$ = this.appService.getUsersOnlineCounter();
  }
}

3. 模板中使用Async管道

<div *ngIf="authService.isLoggedIn()" class="fa fa-user">
  {{ users_online$ | async }}
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 00:15:45