🌟 RxJS 공식문서 의 Overview 부분을 번역하면서 학습한 내용입니다. 중간중간 의역이 들어간 부분이 많습니다. 사실과 다른 부분이 있다면 지적해주시면 감사드리겠습니다 :)
RxJS는 연속된 Observable을 이용하여 비동기와 이벤트 기반의 프로그래밍을 구현하기 위한 라이브러리입니다.
RxJS는 코어 타입 Observable과 위성 타입 (Observer, Schedulers, Subjects) 그리고 Array 메소드에서 착안한 operators (map, filter, reduce, every, etc.. ) 를 제공하여, 비동기 이벤트를 제어합니다.
이벤트 처리에 특화된 Lodash라고 생각해주세요
lodash?
자바스크립트 유틸리티 라이브러리로써 array, collection, date, number, object등이 있으며, 데이터를 쉽게 다룰 수 있도록 도와줍니다.
ReactiveX는 Observer 패턴과 Iterator 패턴을 결합시키고, 함수형 프로그래밍과 collections를 결합하여 연속된 이벤트를 처리하기 위한 이상적인 방식에 대한 니즈를 충족시켜줍니다.
비동기 이벤트 관리를 해결하기위한 RxJS의 주요 컨셉은 다음과 같습니다
Observable
: 향후 얻게될 값이나 이벤트를 호출 할 수 있는 콜렉션에 대한 아이디어를 표현합니다Observer
: Observable이 전달한 값을 어떻게 받을지에 대한 정보가 들어있는 콜백들 콜렉션Subscription
: Observable의 실행을 나타냅니다. 주로 실행을 취소하는데 가장 유용합니다.Operators
: 순수함수이며 map, filter, concat, reduce 같은 기능을 다루면서 함수형 프로그래밍을 가능하게 합니다Subject
: EventEmitter와 동일한 기능을 하고, 다수의 Observer에 데이터값과 이벤트를 전달 할 수 있는 유일한 방법입니다.Schedulers
:동시성(concurrency)을 컨트롤하기 위해 중앙화된 디스패처. setTImeout이나 requestAnimationFrame 등에서 연산이 발생할 때 조정할 수 있음원래는 자바스크립트를 이용하여 이벤트 리스너를 이렇게 등록하죠
document.addEventListener('click', () => console.log("Clicked!"));
RxJS를 이용할경우는? Observable을 만들면 됩니다
import { fromEvent } from 'rxjs';
fromEvent(document, 'click').subscribe(() => console.log("Clicked!"));
RxJS는 순수함수를 이용하여 데이터를 생성할 수 있다는 강점이 있습니다. 즉, 에러를 줄일 수 있음을 의미하죠
보통은 비순수함수를 만들게되어, 다른 코드가 state를 어지럽히게 되는 경우가 생깁니다
let count = 0;
document.addEventListener('click', () => console.log(`Clicked ${++count} times`))
RxJS를 이용하여 state를 묶어둘 수 있습니다
import { fromEvent } from 'rxjs';
import { scan } from 'rxjs/operatores';
fromEvent(document, 'click')
.pipe(scan(count => count + 1, 0))
.subscribe(count => console.log(`Clicked ${count} times`))
Scan 기능은 array의 reduce 메소드 처럼 동작합니다. 콜백에 노출된 값을 인자로 받습니다. 콜백의 리턴값이 이후에 실행될 때 누적되어 이후에 실행될때의 값이됩니다.
RxJS 는 이벤트가 Observer를 통해 흐르는 방식을 제어하는데 도움이 되는 모든 범위의 Operator들을 가지고 있습니다.
초당 최대 한 번의 클릭을 허용하려고 할 때 일반적인 자바스크립트로는 이렇게 할 수 있습니다
let count = 0;
let rate = 1000;
let lastClick = Date.now() - rate;
document.addEventListener('click', () => {
if (Date.now() - lastClick >= rate) {
console.log(`Clicked ${++count} times`);
lastClick = Date.now();
}
})
RxJS는 어떨까요?
import { fromEvent } from 'rxjs';
import { throttleTime, scan } from 'rxjs/operators';
fromEvent(document, 'click')
.pipe(
throttleTime(1000),
scan(count => count + 1, 0)
)
. subscribe(count => console.log(`Clicked ${count} times`));
그밖에도 flow를 컨트롤 할 수 있는 operator는 filter, delay, debounceTime, take, takeUntil, distinct, distinctUntilChanged 등 이 있습니다
Observable을 통해 전달된 값을 변화시키는 것도 가능합니다
아래는 현재 마우스의 x좌표를 매번 클릭마다 추가하는 기능입니다 (자바스크립트버전)
let count = 0;
const rate = 1000;
let lastClick = Date.now() - rate;
document.addEventListener('click', event => {
if (Date.now() - lastClick >= rate) {
count += event.clientX;
console.log(count);
lastClick = Date.now();
}
})
RxJS로 하면?!
import { fromEvent } from 'rxjs';
import { throttleTime, map, scan } from 'rxjs/operators';
fromEvnet(document, 'click')
.pipe(
throttleTime(1000),
map(event => event.clientX),
scan((count, clientX) => count + clientX, 0)
)
.sibscribe(count => console.log(count))
이외에도 value를 조작하는 operato는 pluck, pairwise, sample 등이 있습니다