Observable(관찰 가능 개체)

12606 단어 Angular2
Http 서비스의 각 메서드는 Http Response 객체의 Observable 인스턴스를 반환합니다.우리는 보통 이 Observable 실례를 프로미스트로 바꾸고, 이 프로미스트를 호출자에게 되돌려줍니다. 이 부분에서 우리는 Observable로 직접 돌아가는 것을 배우고, 언제, 왜 그렇게 하는 것이 더 좋은지 토론할 것입니다.
하나.배경의 Observable는 이벤트 흐름입니다. 우리는 그룹 조작부호로 그를 처리할 수 있습니다.Angular 커널은 관찰 가능한 대상에 대한 기본적인 지원을 제공합니다. 우리는 RxJS 대상에서 조작부호와 확장자를 도입할 수 있습니다.우리는 보통 Observable 뒤에 toPromise를 연결합니다. 이 조작부호는 Observable를promise로 변환하고promise를 호출자에게 되돌려줍니다.프로미스로 전환하는 것이 보통 더 좋은 선택입니다. 우리는 http를 요구합니다.get은 단일 블록 데이터를 가져옵니다. 데이터만 받으면 완성됩니다. 프로미스 같은 형식의 결과를 사용하면 호출이 쉽게 작성됩니다.그러나 요청은 항상 일회성이 아니다. 우리는 요청을 시작하고 취소할 수 있다. 서버가 첫 번째 요청에 응답하기 전에 다른 요청을 시작한다. 이런 요청-취소-새로운 요청은promise에 대해 실현하기 어렵지만 Observable에 대해서는 쉽다.
둘.이름별 검색은 사용자가 검색 상자에 이름을 입력할 때 http 요청을 끊임없이 해서 이름별로 필터를 하는 영웅을 얻을 것입니다.
import { Injectable }     from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs';
import { Hero }           from './hero';
@Injectable()
export class HeroSearchService {
  constructor(private http: Http) {}
  search(term: string): Observable {
    return this.http
               .get(`app/heroes/?name=${term}`)
               .map((r: Response) => r.json().data as Hero[]);
  }
}

셋.HeroSearchComponent
<div id="search-component">
  <h4>Hero Searchh4>
  <input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
  <div>
    <div *ngFor="let hero of heroes | async"
         (click)="gotoDetail(hero)" class="search-result" >
      {{hero.name}}
    div>
  div>
div>

Heroes는 현재 영웅 목록의 Observable 대상이지 영웅 그룹이 아니기 때문에 *ngFor는 Observable로 어떤 일도 할 수 없습니다. 그의 뒤에 async pipe를 추가하지 않으면.이 async는 이 Observable에 구독하고,ngFor에 영웅 그룹을 생성합니다.
import { Component, OnInit } from '@angular/core';
import { Router }            from '@angular/router';
import { Observable }        from 'rxjs/Observable';
import { Subject }           from 'rxjs/Subject';
import { HeroSearchService } from './hero-search.service';
import { Hero } from './hero';
@Component({
  moduleId: module.id,
  selector: 'hero-search',
  templateUrl: 'hero-search.component.html',
  styleUrls: [ 'hero-search.component.css' ],
  providers: [HeroSearchService]
})
export class HeroSearchComponent implements OnInit {
  heroes: Observable;
  private searchTerms = new Subject();
  constructor(
    private heroSearchService: HeroSearchService,
    private router: Router) {}
  // Push a search term into the observable stream.
  search(term: string): void {
    this.searchTerms.next(term);
  }
  ngOnInit(): void {
    this.heroes = this.searchTerms
      .debounceTime(300)        // wait for 300ms pause in events
      .distinctUntilChanged()   // ignore if next search term is same as previous
      .switchMap(term => term   // switch to new observable each time
        // return the http search observable
        ? this.heroSearchService.search(term)
        // or the observable of empty heroes if no search term
        : Observable.of([]))
      .catch(error => {
        // TODO: real error handling
        console.log(error);
        return Observable.of([]);
      });
  }
  gotoDetail(hero: Hero): void {
    let link = ['/detail', hero.id];
    this.router.navigate(link);
  }
}

넷.검색어 잘 보세요. 검색어 잘 보세요.
private searchTerms = new Subject<string>();

// Push a search term into the observable stream.
search(term: string): void {
  this.searchTerms.next(term);
}

ject는 관찰할 수 있는 이벤트 흐름의 생산자입니다. 검색 Terms는 문자열을 생성하는 Observable를 생성하여 이름으로 검색할 때 필터 조건으로 사용합니다.
검색을 호출할 때마다next를 호출해서 이 테마의 관찰 가능한 흐름에 새 문자열을 넣습니다.
오.Heroes 속성 초기화subject도 Observable 대상입니다. 검색어의 흐름을 Hero 그룹의 흐름으로 바꾸고 결과를 Heroes 속성에 부여합니다.
heroes: Observable;

ngOnInit(): void {
  this.heroes = this.searchTerms
    .debounceTime(300)        // wait for 300ms pause in events
    .distinctUntilChanged()   // ignore if next search term is same as previous
    .switchMap(term => term   // switch to new observable each time
      // return the http search observable
      ? this.heroSearchService.search(term)
      // or the observable of empty heroes if no search term
      : Observable.of([]))
    .catch(error => {
      // TODO: real error handling
      console.log(error);
      return Observable.of([]);
    });
}

만약 우리가 모든 사용자 버튼을 Hero Search 서비스에 직접 전송한다면 HTTP 요청 폭풍이 일어날 것입니다. 그러나 우리는 문자열 Observable 뒤에 Observable 조작부호를 연결해서 이 요청들을 합칠 수 있습니다.HeroSearch Service에 대해 더 적은 호출을 시작하고 충분한 대응을 얻을 것입니다. (1) 최종 문자열이 전송되기 전에 debounce (300) 는 새 문자열의 이벤트가 300밀리초 동안 중단될 때까지 기다릴 것입니다. (2) distinctUntilChange는 필터 조건만 바뀌어야 요청을 보낼 수 있습니다. (3) switchMap은 debounce와distinctUntilChage에서 통과한 검색어에 대한 검색 서비스를 호출합니다.그는 관찰할 수 있는 이전의 검색을 취소하고 버릴 것이며, 가장 가까운 것만 보류할 것이다.
switchMap 조작부호는 매우 지능적이다.조건에 맞는 버튼 이벤트마다 http 방법에 대한 호출을 터치합니다.모든 요청을 보내는 데 300밀리초의 지연이 있어도, 우리는 여전히 도중에 있는 http 요청을 동시에 가지고 있을 수 있으며, 이전의 호출이 취소되거나 버려졌기 때문에, 최근의 http 호출이 되돌아오는 관찰 대상만 되돌아갈 수 있다.만약 검색 상자가 비어 있다면, 우리는 이번 http 방법 호출을 단락으로 하고, 빈 그룹을 포함하는 관찰 가능한 대상을 직접 되돌릴 수 있습니다.주의: Herosearch 서비스의 관찰 대상을 취소하는 것은 서비스가 이 기능을 지원하지 않는 한 미완성 http 요청을 종료하지 않습니다.
RxJS 조작부호 가져오기 Angular의 기본 Observable 구현에서 RxJS 조작부호는 사용할 수 없습니다. Observable를 확장하기 위해 가져와야 합니다.이 파일의 맨 위에 import 문장을 쓰면 Observable에서 사용할 조작부호를 확장할 수 있습니다.다른 방법도 쓸 수 있어요.
// Observable class extensions
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/throw';

// Observable operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';

그런 다음 최상위 AppModule에서 파일을 한 번에 가져옵니다.
import './rxjs-extensions';

좋은 웹페이지 즐겨찾기