Angular2 http.get() ,map(), subscribe() 和可观察模式——基本理解

Angular2 http.get() ,map(), subscribe() and observable pattern - basic understanding

现在,我有一个初始页面,其中有三个 link。单击最后一个 'friends' link 后,将启动相应的好友组件。在那里, 我想 fetch/get 我的朋友列表存储到 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.

       }
  }

请正确指导和解释。我知道这对很多新开发人员来说非常有益。

这里是你出错的地方:

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- 您将可观察对象本身分配给 this.result。当您实际上想将朋友列表分配给 this.result 时。正确的做法是:

  • 您订阅了 observable。 .subscribe 是实际执行可观察对象的函数。它需要三个回调参数如下:

    .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")}
);

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

2- 第二个错误,您在 .map(res => res.json()) 上调用了 .json(),然后在可观察对象的成功回调中再次调用了它。 .map() 是一个转换器,它将结果转换为任何你 return (在你的情况下 .json()),然后再传递给成功回调 你应该在其中任何一个上调用一次。

概念

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

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

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

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

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

下面是对此类用例的更广泛描述:

AngularConnect 2015 和 EggHead 上有两个精彩的演讲:

Christoph Burgdorf 也写了一些关于这个主题的精彩博文:

正在行动

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

  • 自己管理可观察对象。在这种情况下,您负责调用可观察对象的 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 方法的

    Returns 是可观察的而不是结果(与承诺的方式相同)。

  • 让我们通过 Angular 模板 管理可观察对象。您还可以利用 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());
       }
    }
    

您会注意到可观察对象是惰性的。因此,相应的 HTTP 请求只会调用一次使用 subscribe 方法附加在其上的侦听器。

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

希望这对你有帮助, 蒂埃里

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);