2017-02-11 6 views
2

Кажется, мне не удается создать переменную для представления с информацией из json-файла, но я так близко. Я могу выделить информацию в файле .subscribe() -chain, но он не будет привязан к переменной, они просто становятся неопределенными, что я делаю неправильно?Как извлечь данные JSON из http.get в Angular 2 правильно?

Я просто хочу загрузить файл json в переменную в представлении компонента. Это было легко в Угловом 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() { 
    } 

} 

на основе текущего кода этого является то, что я получаю:

result

У меня есть проект здесь: github.

ответ

2

Это асинхронная операция, поэтому при попытке выполнить 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 вместо. Здесь вы также можете заметить, что значения не мгновенно доступны вне подписки в соответствии с комментариями в коде. Так что если вы хотите, чтобы манипулировать данными каким-то образом, вы должны принять это во внимание :)

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

AS это операция асинхронной, так что будьте готовы использовать либо ngIf или safe navigation operator на ваш взгляд, так как представление отображается до того, как данные были восстановлены.

Так или обернуть ваш код внутри ngIf:

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

или {{gullkorn?.someProperty}}

+0

СПАСИБО! Это работало с первой попытки, была для меня такой борьбой. Цените свое время много. Вызов функции с подпиской в ​​компоненте сделал трюк! –

+1

Добро пожаловать! Да, я понимаю. Асинхронные операции очень запутанны в начале! В моем ответе добавлен еще немного контекста, например.g, если вам нужно каким-то образом манипулировать данными в компоненте при навигации по странице, вам нужно заметить, где данные доступны в подписке, а где нет, подумал, что это может быть полезно для будущего :) Счастливое кодирование! :) – Alex

1

Это лучше вернуться наблюдаемым от службы и подписаться на него в компоненте:

обслуживание:

@Injectable() 
export class GullkornService { 

    constructor(private http:Http) { 
    } 

    getGullkorn() { 
    // Return the observable here 
    return this.http.get('./gk/gullkorn.json') 
    .map(res => res.json()); 
    } 

} 

comp onent:

@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() { 
    } 

} 
+0

Спасибо! Вот как я это делаю сейчас. Но им интересно новое, когда или как я должен отказаться от подписки на это, или это произойдет автоматически? –

+0

вы можете подписаться на 'ngOnInit' и отказаться от подписки в' ngOnDestroy' –