2016-11-22 166 views
1
import { Injectable }  from '@angular/core'; 
import { Http, Response, Headers, RequestOptions } from '@angular/http'; 
import { Observable } from 'rxjs/Rx'; 

// Import RxJs required methods 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/catch' 

@Injectable() 
export class EquipmentService{ 
    data: any; 
    constructor(private http:Http){ 

    } 
    getDefaultEquipment(){ 
     this.http.get('./app/SaveData/equipmentTest.json') 
      .map((res:Response) => res.json()) 
      .subscribe(data => { this.data = data}, 
       err => console.error(err), 
       () => console.log(this.data)); 
    } 
} 

從文件中讀取數據,重要的是getDefaultEquipment()Angular 2 observable如何提取響應?

如果您看到最後一個console.log(this.data)數據是正確的,那正是我所需要的。但如果我return this.http.get(...() => {return this.data})我得到未定義。我如何獲得並返回此數據?

很顯然,如果我編寫另一個如下所示的返回值,那麼observable尚未完成,因此它將返回空數據:any。

//clearly won't work because the get hasn't returned yet 
getDefaultEquipment(){ 
    this.http.get(...data => {this.data = data}...); 
    return this.data; 
} 
+0

只需返回您的可觀察值。您不需要將異步呼叫轉換爲同步呼叫。 – Cleiton

+0

您無法返回數據。不要訂閱。只要返回可觀察的。調用者將是訂閱者,並將獲得傳遞給subscribe()的回調函數中的數據。 –

+0

太棒了。那就是訣竅。在我的設備組件'this.equipmentService.getDefaultEquipment()中添加了訂閱方法subscribe( stuff => {console.log(stuff)}, );'謝謝。 –

回答

4

以下是我對它的看法。未經測試,但概念是堅實的。由於async管道基本上吃Observables,這將爲您節省很多樣板代碼。如果您需要做一些轉換,那麼在返回可觀察值之前也可以做這些轉換。你可以在服務中做到這一點,或者你可以在組件中做到這一點。請記住關於Observables的事情,如果您有多個訂戶,請務必使用.share()運營商,否則您將爲每個訂戶執行一次(在此情況下)http.get.do運營商也可以派上用場,但也可以像用戶一樣行事。

我會推薦閱讀RxJs,並參考關於異步管道用法的angulars網站的示例。

的角AsyncPipe是不純的管的一個有趣的例子。 AsyncPipe接受Promise或Observable作爲輸入並自動訂閱輸入,最終返回發出的值。

equipment.service.ts

import { Injectable } from '@angular/core'; 
import { Observable } from 'rxjs/Rx'; 

export interface Equipment { 
    name: string; 
    id: string; 
} 

@Injectable() 
export class EquipmentService { 

    constructor(private http:Http){} 

    public getDefaultEquipment(): Observable<Equipment[]> { 
    return this.http 
    .get('./app/SaveData/equipmentTest.json') 
    .map((res:Response) => res.json()); 
    } 
} 

設備-list.component.ts

import { Component, OnInit } from "@angular/core"; 
import { EquipmentService, Equipment } from "./services/equipment.service"; 
import { Observable } from 'rxjs/Rx'; 

@Component({ 
    selector: 'equipment-list', 
    templateUrl: './equipment-list.component.html', 
    styleUrls: ['./equipment-list.component.css'], 
    providers:[ 
    EquipmentService 
    ] 
}) 
export default class EquipmentComponent { 

    constructor(private service: EquipmentService) {} 

    public get equipment():Observable<Equipment[]> { 
     return this.service.getDefaultEquipment(); 
    } 
} 

設備-list.component.html

<ul> 
    <li *ngFor="item of (equipment | async)> 
     <span>{{item.id}}</span> 
     <span>{{item.name}} 
    </li> 
</ul> 
+3

當他們有一些解釋時,答案是最好的。簡單地說「這樣做」並不能幫助我們理解*爲什麼它會以這種方式運作,並且如果出現類似的情況,也不會對我們有所幫助。 –

+1

對不起。有一個missclick並在解釋完成之前發佈。 – abdavid

+0

@abdavid的答案是正確和好的,雖然我不會寫'.map((res:Response)=> res.json());'對一個服務,因爲我想讓我的組件**反應**響應:讀取頭文件,狀態代碼等 – Aitch