옵저버블 (Observable)
옵저버블 (Observable) 이란 데이터 스트림을 생성하는 객체를 말한다.
옵저버(Observer)는 데이터 스트림을 구독하여 사용하는 객체를 를 말한다.
일반적인 비동기 처리에 있어서 사용하는 callback함수나 Promise의 문제점
1) 한번에 하나의 데이터를 처리한다.
2) 서버로 보낸 요청을 취소할 수 없다.
Angular에서 날씨데이터를 가져오는 http 요청에 있어서 옵저버블을 구현해 보자.
출처 : Angular Development with TypeScript - 한장현
이 책에서 좋은 예제들을 제공한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { NgModule, Component } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { HttpModule, Http } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/switchMap'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/catch'; import 'rxjs/add/observable/of'; @Component({ selector : 'app', template : ` <h2>Observable weather</h2> <input type="text" placeholder="Enter city" [formControl]="searchInput"> <h3>{{ temperature }}</h3> ` }) export class AppComponent { private baseWeatherURL : string = 'http://api.openweathermap.org/data/2.5/weather?q='; private urlSuffix : string = '&units=metric&appid=[YOUR KEY]'; searchInput : FormControl = new FormControl(); temperature : string; constructor (private http : Http) { this.searchInput.valueChanges .debounceTime(200) .switchMap(city => this.getWeather(city)) .subscribe( res => { this.temperature = `Current temperature is ${res['main'].temp}℃, ` + `humidity: ${res['main'].humidity}%`; }, err => console.log("Can't get weather. Error code: %s, URL: %s", err.message, err.url), () => console.log("Weather is retrieved") ); } getWeather (city : string) : Observable<Array<string>> { return this.http.get(this.baseWeatherURL + city + this.urlSuffix) .map(res => { console.log(res.json()); return res.json(); }) .catch(err => { if (err.status === 404) { console.log(`City ${city} not found`); return Observable.of(); } // empty observable }); } } @NgModule({ imports : [BrowserModule, ReactiveFormsModule, HttpModule], declarations : [AppComponent], bootstrap : [AppComponent] }) class AppModule {} platformBrowserDynamic().bootstrapModule(AppModule); | cs |
line 18 : searchInput 이라는 컴포넌트 프로퍼티로 바인딩 된다.
line 31 ~ :
함수들을 공식 RxJS 문서에서 발췌했다.
DebounceTime
debounceTime delays emitted by the source Observable, but drops previous delayed emissions if a new value arrives on the source Observable.
새로운 옵저버블이 들어오면 이전에 지연된 것들을 드랍한다고 한다.
" It's like delay, but passes only the most recent value from each burst of emissions. "
이 함수를 사용하지 않는다면 입력할 때 마다 이벤트가 발생할 것이다. 그래서 적당한 지연시간을 주는 것이다.
swithMap
Map to observable, complete previous inner observable, emit values
쓰는 이유는 효과를 취소하는데에 있다고 한다.
On each emission the previous inner observable (the result of the function you supplied) is cancelled and the new observable is subscribed. You can remember this by the phrase switch to a new observable.
옵저버블을 받아서 새로운 옵저버블을 반환한다.
subscribe
속도가 한참 느려졌다. 보면 404 error를 뿜는데 이것은 도중에 계속 계속 http요청이 가는 것을 종료시켜버린 결과이다.
즉 옵저버블을 사용하면 아주 간단하게 불필요한 서버 요청을 취소하고 결과를 확인할 수 있다.
'프로그래밍 > Angular' 카테고리의 다른 글
[Angular] 프로젝션, 쉐도우 돔 (Shadow DOM)의 역할 (0) | 2017.12.30 |
---|