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

调用Angular Service时组件获取数据为undefined的原因排查

为什么Angular组件调用Service获取数据时返回undefined?

我正在使用JSONPlaceholder Fake API获取数据,在Service中能够获取到API返回的数据,但在AppComponent中调用该Service时却得到undefined。以下是我的代码:

Service.ts 代码

import { Injectable } from '@angular/core';
import { Http, URLSearchParams, Response, RequestOptions, Headers } from '@angular/http';
import 'rxjs/RX';
import 'rxjs/add/operator/map';

@Injectable()
export class InfiniteService {
  apiRoot: string = 'https://jsonplaceholder.typicode.com/comments?';
  postId = 1;
  data;

  constructor(private _http: Http) {
    this._http.get(this.apiRoot).subscribe((data) => {
      this.data = data.json();
    });
  }

  init() {
    return this.data;
  }
}

组件代码

import { Component, OnInit } from '@angular/core';
import { InfiniteService } from './infinite.service';
import 'rxjs/add/operator/map';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  data;

  constructor(private _infinteService: InfiniteService) {
    this.data = this._infinteService.init();
    console.log(this.data);
  }

  GetPosition($event) {
    if ($event == 'Bottom') {
      console.log($event);
    } else {
      console.log($event);
    }
  }

  ngOnInit() {
  }
}

问题根源:异步操作的时机问题

你看哈,HTTP请求是异步操作——当你在Service的构造函数里发起this._http.get()请求时,浏览器会后台去请求数据,这时候代码不会等着请求完成,而是继续往下走。

当AppComponent的构造函数调用this._infinteService.init()时,Service里的HTTP请求大概率还没完成,this.data还没被赋值,所以自然返回undefined。

修正方案:用Observable传递异步数据

咱们得换个思路,不要在Service里存数据然后同步返回,而是让Service返回HTTP请求的Observable,组件自己订阅这个Observable,等数据回来再处理。

修正后的Service代码

import { Injectable } from '@angular/core';
import { Http, URLSearchParams, Response, RequestOptions, Headers } from '@angular/http';
import 'rxjs/RX';
import 'rxjs/add/operator/map';

@Injectable()
export class InfiniteService {
  apiRoot: string = 'https://jsonplaceholder.typicode.com/comments?';
  postId = 1;

  constructor(private _http: Http) { }

  // 把请求封装成返回Observable的方法
  getData() {
    return this._http.get(this.apiRoot)
      .map((response: Response) => response.json()); // 直接在Service里处理json转换
  }
}

修正后的组件代码

import { Component, OnInit } from '@angular/core';
import { InfiniteService } from './infinite.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  data;

  constructor(private _infinteService: InfiniteService) { }

  // 把数据获取逻辑放到ngOnInit里(Angular推荐的初始化时机)
  ngOnInit() {
    this._infinteService.getData().subscribe((result) => {
      this.data = result;
      console.log(this.data); // 这时候数据就有了!
    });
  }

  GetPosition($event) {
    if ($event == 'Bottom') {
      console.log($event);
    } else {
      console.log($event);
    }
  }
}

额外小提示

  1. 尽量不要在组件构造函数里做数据获取操作,ngOnInit是Angular专门用来做初始化逻辑的钩子,更合适。
  2. 如果你需要复用获取到的数据,可以在Service里缓存Observable或者数据,避免重复发起请求。

内容的提问来源于stack exchange,提问作者Chellappan 喈�,angular"

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:24:28