【问题标题】:How to extract JSON data from http.get in Angular 2 properly?如何正确地从 Angular 2 中的 http.get 中提取 JSON 数据?
【发布时间】:2026-01-05 15:50:01
【问题描述】:

我似乎无法使用 json 文件中的信息为视图创建一个变量,但我已经很接近了。我可以回显.subscribe()-chain 中的信息,但它不会将其设置为变量,它们只是未定义,我做错了什么?

我只想将我的 json 文件加载到组件视图中的变量中。在 Angular 1 中这很容易。

我的服务:

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

@Injectable()
export class GullkornService { 
result: any;

constructor(private http:Http) {
}

getGullkorn()  {

let result = this.result;
this.http.get('./gk/gullkorn.json')
.map(res => res.json())
.subscribe(
        val => this.result = val,
        err => console.error(err),
        () =>  console.log(this.result));  // this one echoes out what i want
        console.log(this.result); // but this one doesnt, so i cant return it 
      }
}

以及登陆组件:

import { Component, OnInit } from '@angular/core';
import {Router, RouterOutlet} from '@angular/router';
import { HttpModule, JsonpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule }      from '@angular/core';
import { GullkornService } from '../../gullkorn-service.service';
import { FormsModule }   from '@angular/forms';
import {Observable} from 'rxjs/Observable';

import "gsap";
declare var ease, TimelineMax,TweenMax,Power4,Power1,Power2,Power3,Bounce, Elastic:any;

@Component({
  selector: 'gullkorn-visning',
  providers: [GullkornService],
  templateUrl: './landing.component.html',
  styleUrls: ['./landing.component.css']
})
export class LandingComponent implements OnInit {
  gullkorn: any;
  constructor(GullkornService: GullkornService) { 
        this.gullkorn = GullkornService.getGullkorn();
        console.log(this.gullkorn);
  }

  ngOnInit() {
  }

}

根据当前代码,这是我得到的:

我有这个项目:github

【问题讨论】:

    标签: angular angular2-services


    【解决方案1】:

    这是一个异步操作,因此当您尝试 console.log 时,结果是未定义的,因为它在订阅内的其他 console.log 之前运行。

    .subscribe(
            val => this.result = val,
            err => console.error(err),
            () =>  console.log(this.result));  // is run sometimes later
            console.log(this.result); // is run first
          }
    

    我将对您的代码进行一些更改...我建议您改为处理组件中的订阅,这将是处理 http 请求的最佳方式。所以只需在服务中map 并将可观察对象返回给组件,记得添加return 声明:

    getGullkorn() {
      return this.http.get('./gk/gullkorn.json')
        .map(res => res.json())
    }
    

    在您的组件中,我建议您将服务调用移至OnInit。在这里,您还可以注意到,根据代码中的 cmets,在订阅之外无法立即访问这些值。所以如果你想以某种方式操纵你的数据,你需要考虑到这一点:)

    ngOnInit() {
      this.GullkornService.getGullkorn()
        .subscribe(data => {
         // is run sometimes later
         this.gullkorn = data
      });
      // is run first
    }
    

    由于这是一个异步操作,因此请准备好在您的视图中使用 ngIfsafe navigation operator,因为视图是在检索数据之前呈现的。

    所以要么将你的代码包装在ngIf

    <div *ngIf="gullkorn"></div>
    

    {{gullkorn?.someProperty}}

    【讨论】:

    • 谢谢!这在第一次尝试时起作用,对我来说真是一场斗争。非常感谢您的时间。在组件中使用 subscribe 调用函数就可以了!
    • 不客气!是的,我明白了。异步操作一开始非常混乱!仍然在我的回答中添加了更多上下文,例如,如果您需要在导航到页面时以某种方式操作组件中的数据,您需要注意订阅中数据在哪里可用,在哪里不可用,认为它可能对未来 :) 编码快乐! :)
    【解决方案2】:

    最好从服务中返回 observable 并在组件中订阅它:

    服务:

    @Injectable()
    export class GullkornService {
    
      constructor(private http:Http) {
      }
    
      getGullkorn()  {
        // Return the observable here
        return this.http.get('./gk/gullkorn.json')
        .map(res => res.json());
      }
    
    }
    

    组件:

    @Component({
      selector: 'gullkorn-visning',
      providers: [GullkornService],
      templateUrl: './landing.component.html',
      styleUrls: ['./landing.component.css']
    })
    export class LandingComponent implements OnInit {
      gullkorn: any;
      constructor(GullkornService: GullkornService) { 
          GullkornService.getGullkorn()
            .subscribe(
                val => this.gullkorn = val,
                err => console.error(err)
      }
    
      ngOnInit() {
      }
    
    }
    

    【讨论】:

    • 谢谢!这就是我现在的做法。但我想知道一个新事物,我应该何时或如何取消订阅,还是自动发生?
    • 您可以在ngOnInit订阅和在ngOnDestroy退订