Angular 2 observable 我如何提取响应?

Posted

技术标签:

【中文标题】Angular 2 observable 我如何提取响应?【英文标题】:Angular 2 observable How do I extract response? 【发布时间】:2017-04-06 18:32:05 【问题描述】:
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()

如果你看到最后一个 console.log(this.data) 数据是正确的,这正是我需要的。但如果我return this.http.get(... () => return this.data) 我得到未定义。如何获取并返回 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;

【问题讨论】:

返回你的 observable。您不需要将异步调用转换为同步调用。 您无法返回数据。不要订阅。只需返回可观察的。调用者将是订阅者,并将获取传递给 subscribe() 的回调函数中的数据。 太棒了。那成功了。在我的设备组件this.equipmentService.getDefaultEquipment().subscribe( stuff => console.log(stuff), );中为调用者添加订阅方法@谢谢。 【参考方案1】:

以下是我的看法。未经测试,但这个概念是可靠的。这将为您节省大量样板代码,因为 async 管道基本上吃掉了 Observables。如果你需要做一些转换,那么在返回 observable 之前也是可能的。您可以在服务中执行此操作,也可以在组件中执行此操作。只要记住关于Observables 的事情,如果您有多个订阅者,请务必使用.share() 运算符,否则您将为每个订阅者执行(在这种情况下)http.get 一次。 .do 运算符也是如此,它可以派上用场,但也可以像订阅者一样。

我建议阅读 RxJs 并查看 angulars 网站上有关异步管道用法的示例。

http://blog.angular-university.io/functional-reactive-programming-for-angular-2-developers-rxjs-and-observables/ https://angular.io/docs/ts/latest/guide/pipes.html

Angular AsyncPipe 是不纯管道的一个有趣示例。 AsyncPipe 接受 Promise 或 Observable 作为输入并自动订阅输入,最终返回发出的值。

设备.服务.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());
  

设备列表.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();
    

设备列表.component.html

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

【讨论】:

最好有一些解释的答案。简单地说“这样做”并不能帮助我们理解为什么它会以这种方式工作,因此如果出现类似情况也无济于事。 对不起。在解释完成之前有一个missclick并发布。 @abdavid 的回答是正确且好的,虽然我不会将.map((res:Response) =&gt; res.json()); 写入服务,因为我希望我的组件对响应反应:读取标题, 状态码等 如果您有一个组件需要对特定标题做出反应,那么可以将.map((res:Response) =&gt; res.json()); 移动到需要的地方。对于这个例子,虽然它应该足够了,但感谢你澄清这一点。 这真的很有见地,并帮助澄清了我遇到的一些实施问题。感谢 res:Response => res.abdavid() ;)

以上是关于Angular 2 observable 我如何提取响应?的主要内容,如果未能解决你的问题,请参考以下文章

如何在模板 Angular 2 中呈现 observables 数组长度

如何在 Angular 2 Http Observable 请求中设置间隔

Angular 2:将 Observable 转换为 Promise

Angular 2 路由器使用 Observable 解析

Typescript Angular - Observable:如何更改其值?

Angular 6 / Rxjs - 如何基础:observables 成功,错误,最后