Angular2 http.get() ,map(), subscribe() 和 observable 模式 - 基本理解

Posted

技术标签:

【中文标题】Angular2 http.get() ,map(), subscribe() 和 observable 模式 - 基本理解【英文标题】:Angular2 http.get() ,map(), subscribe() and observable pattern - basic understanding 【发布时间】:2016-04-12 19:42:34 【问题描述】:

现在,我有一个初始页面,其中包含三个链接。单击最后一个“朋友”链接后,将启动适当的朋友组件。在那里, 我想获取/获取存储在 friends.json 文件中的朋友列表。 到目前为止,一切正常。但是我仍然是使用 RxJs 的 observables、map、subscribe 概念的 angular2 的 HTTP 服务的新手。我试图理解它并阅读了几篇文章,但在我开始实际工作之前,我不会正确理解这些概念。

这里我已经制作了 plnkr,它除了 HTTP 相关的工作之外都在工作。

Plnkr

myfriends.ts

 import Component,View,CORE_DIRECTIVES from 'angular2/core';
 import Http, Response,HTTP_PROVIDERS from 'angular2/http';
 import 'rxjs/Rx';
 @Component(
    template: `
    <h1>My Friends</h1>
    <ul>
      <li *ngFor="#frnd of result">
          frnd.name is frnd.age years old.
      </li>
    </ul>
    `,
    directive:[CORE_DIRECTIVES]
  )

  export class FriendsList

      result:Array<Object>; 
      constructor(http: Http)  
        console.log("Friends are being called");

       // below code is new for me. So please show me correct way how to do it and please explain about .map and .subscribe functions and observable pattern.

        this.result = http.get('friends.json')
                      .map(response => response.json())
                      .subscribe(result => this.result =result.json());

        //Note : I want to fetch data into result object and display it through ngFor.

       
  

请正确引导和解释。我知道这对许多新开发者来说是非常有益的。

【问题讨论】:

【参考方案1】:

这是你出错的地方:

this.result = http.get('friends.json')
                  .map(response => response.json())
                  .subscribe(result => this.result =result.json());

应该是:

http.get('friends.json')
                  .map(response => response.json())
                  .subscribe(result => this.result =result);

http.get('friends.json')
                  .subscribe(result => this.result =result.json());

你犯了两个错误:

1- 您将 observable 本身分配给 this.result。当您真正想将朋友列表分配给this.result 时。正确的做法是:

你订阅了 observable。 .subscribe 是实际执行 observable 的函数。它需要三个回调参数,如下:

.subscribe(success, failure, complete);

例如:

.subscribe(
    function(response)  console.log("Success Response" + response),
    function(error)  console.log("Error happened" + error),
    function()  console.log("the subscription is completed")
);

通常,您从成功回调中获取结果并将其分配给您的变量。 错误回调是不言自明的。 完整的回调用于确定您已收到最后的结果,没有任何错误。 在您的 plunker 上,完成回调将始终在成功或错误回调之后调用。

2- 第二个错误,你在 .map(res =&gt; res.json()) 上调用了 .json(),然后你在 observable 的成功回调上再次调用它。 .map() 是一个转换器,它将在将结果传递给成功回调之前将结果转换为您返回的任何内容(在您的情况下为 .json()) 您应该在其中任何一个上调用一次。

【讨论】:

给你your plunker。我在 myfriends.ts 上更改了行:21、23 我不明白为什么要在这里使用“地图”功能?我们可以在结果上调用 .json。那么这样做有什么好处呢? 你是对的@rubmz。正如我在回答中提到的那样,您可以这样做。但是,一个巨大的好处是分离逻辑。例如,在您的服务中,您有一个函数getFriends()return http.get('friends.json').map(r =&gt; r.json());。现在,您可以拨打getFriends().subscribe(...),而无需每次都拨打.json() 是的,这对新手来说有点混乱。那个神秘的 map() 能做什么,不能做什么......但最后我也明白了:) @Abdulrahman,也许你也有兴趣看看这个问题:***.com/questions/40505691/…【参考方案2】:

概念

简而言之,可观察对象处理异步处理和事件。与 promises 相比,这可以描述为 observables = promises + events。

observable 的优点在于它们是惰性的,它们可以被取消,并且您可以在其中应用一些运算符(例如 map,...)。这允许以非常灵活的方式处理异步事物。

描述 observables 的最佳功能的一个很好的示例是将过滤器输入连接到相应的过滤列表的方法。当用户输入字符时,列表被刷新。 Observables 处理相应的 AJAX 请求,如果另一个请求被输入中的新值触发,则取消先前正在进行的请求。下面是对应的代码:

this.textValue.valueChanges
    .debounceTime(500)
    .switchMap(data => this.httpService.getListValues(data))
    .subscribe(data => console.log('new list values', data));

textValue 是与过滤器输入关联的控件)。

以下是对此类用例的更广泛描述:How to watch for form changes in Angular 2?。

在 AngularConnect 2015 和 EggHead 上有两个很棒的演讲:

可观察与承诺 - https://egghead.io/lessons/rxjs-rxjs-observables-vs-promises 创建可观察的 - https://egghead.io/lessons/rxjs-creating-an-observable RxJS 深入了解https://www.youtube.com/watch?v=KOOT7BArVHQ Angular 2 数据流 - https://www.youtube.com/watch?v=bVI5gGTEQ_U

Christoph Burgdorf 还写了一些关于该主题的精彩博文:

http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

在行动

事实上,关于您的代码,您混合了两种方法 ;-) 它们是:

自行管理 observable。在这种情况下,您有责任在 observable 上调用 subscribe 方法并将结果分配给组件的属性。然后,您可以在视图中使用此属性来迭代集合:

@Component(
  template: `
    <h1>My Friends</h1>
    <ul>
      <li *ngFor="#frnd of result">
        frnd.name is frnd.age years old.
      </li>
    </ul>
  `,
  directive:[CORE_DIRECTIVES]
)
export class FriendsList implement OnInit, OnDestroy 
  result:Array<Object>; 

  constructor(http: Http) 
  

  ngOnInit() 
    this.friendsObservable = http.get('friends.json')
                  .map(response => response.json())
                  .subscribe(result => this.result = result);
   

   ngOnDestroy() 
     this.friendsObservable.dispose();
   

getmap 方法的返回值是 observable 而不是结果(与 promise 相同)。

让我们通过 Angular 模板管理 observable。您还可以利用async 管道隐式管理可观察对象。在这种情况下,不需要显式调用subscribe 方法。

@Component(
  template: `
    <h1>My Friends</h1>
    <ul>
      <li *ngFor="#frnd of (result | async)">
        frnd.name is frnd.age years old.
      </li>
    </ul>
  `,
  directive:[CORE_DIRECTIVES]
)
export class FriendsList implement OnInit 
  result:Array<Object>; 

  constructor(http: Http) 
  

  ngOnInit() 
    this.result = http.get('friends.json')
                  .map(response => response.json());
   

你可以注意到 observables 是惰性的。因此相应的 HTTP 请求只会在使用 subscribe 方法附加在其上的侦听器时被调用一次。

您还可以注意到,map 方法用于从响应中提取 JSON 内容,然后在可观察处理中使用它。

希望对你有帮助, 蒂埃里

【讨论】:

感谢所有参考。但是你能帮我解决我的问题吗? 我更新了我的答案,提供了有关您的代码的更多详细信息。希望它会帮助你;-) 对不起,我不能接受你的回答。更清楚但被接受和赞赏的答案帮助我充分理解了我的问题。但希望您能获得更详细的解释,从而获得明确的答案。也接受了很好的基本理解的答案。 Thierry Templier 这是一个很好的答案,但有一件事我不清楚,我认为 http.get('friends.json') .map(response => response.json()) 返回 observable >。如果是,那么您如何将其发送到 this.result?它们是不同的类型。 @StavAlfi pipes 也是一个observables。观看此视频:youtube.com/watch?v=bVI5gGTEQ_U thierry 建议了解更多信息。【参考方案3】:
import  HttpClientModule  from '@angular/common/http';

HttpClient API 是在 4.3.0 版本中引入的。它是现有 HTTP API 的演变,并拥有自己的包 @angular/common/http。 最显着的变化之一是现在响应对象默认为 JSON,因此不再需要使用 map 方法解析它。我们可以直接使用如下

http.get('friends.json').subscribe(result => this.result =result);

【讨论】:

以上是关于Angular2 http.get() ,map(), subscribe() 和 observable 模式 - 基本理解的主要内容,如果未能解决你的问题,请参考以下文章

获取状态码 http.get 响应 angular2

Angular 2 observable 没有“映射”到模型

Angular2 HTTP GET - 将响应转换为完整对象

Angular2:http.get 返回“请求的资源上不存在‘Access-Control-Allow-Origin’标头。”

Ionic2,Angular2:如何在使用 http get 进行 REST API 服务调用时避免 CORS 问题?

Angular 2:第一个服务成功后的两个后端服务调用