프론트엔드/JavaScript
RxJS - 연산자 1
lifecarelog
2022. 9. 9. 16:08
반응형
산수 관련 Operator
const { of } = rxjs
const { count, max, min, reduce } = rxjs.operators
const obs$ = of(4, 2, 6, 10, 8)
obs$.pipe(count()).subscribe(x => console.log('count: ' + x)) // 총 몇개가 있는지 갯수를 발행
obs$.pipe(max()).subscribe(x => console.log('max: ' + x)) // 가장 큰 값을 발행
obs$.pipe(min()).subscribe(x => console.log('min: ' + x)) // 가장 작은 값을 발행
obs$.pipe(
reduce((acc, x) => { return acc + x }, 0)
).subscribe(x => console.log('reduce: ' + x)) // js reduce와 동일
선택 관련 Operator
first, last, elementAt, distinct, filter
- 꼭 배열이 아니고 시간이나 이벤트에도 사용할 수 있다.
const { from } = rxjs
const { first, last, elementAt, filter, distinct } = rxjs.operators
const obs$ = from([
9, 3, 10, 5, 1, 10, 9, 9, 1, 4, 1, 8, 6, 2, 7, 2, 5, 5, 10, 2
])
obs$.pipe(first()).subscribe(x => console.log('first: ' + x)) // 첫 번째 값을 발행
obs$.pipe(last()).subscribe(x => console.log('last: ' + x)) // 마지막 값을 발행
obs$.pipe(elementAt(5)).subscribe(x => console.log('elementAt: ' + x)) // 인자로 들어간 숫자에 해당하는 index 값을 발행 (index는 0부터 시작)
obs$.pipe(distinct()).subscribe(x => console.log('distinct: ' + x)) // 중복을 제거하고 각각의 요소들을 처음 한 번만 발행
obs$.pipe(
filter(x => x % 2 === 1)
).subscribe(x => console.log('filter: ' + x)) // 조건에 해당하는 값들만 발행
🎯 활용해보기
위의 숫자들 중
- 짝수들 중에서 가장 큰 수
obs$.pipe(
filter(x => x % 2 === 0),
max()
)
- 5보다 큰 3번째 짝수
obs$.pipe(
filter(x => x > 5),
filter(x => x % 2 === 0),
elementAt(2)
)
- 한 번 이상 나온 홀수들의 갯수, 합
obs$.pipe(
distinct(),
filter(x => x % 2 === 0),
count()
)
obs$.pipe(
distinct(),
filter(x => x % 2 === 0),
reduce((acc, x) => { return acc + x }, 0)
)
tap Operator
const { from } = rxjs
const { tap, filter, distinct } = rxjs.operators
from([
9, 3, 10, 5, 1, 10, 9, 9, 1, 4, 1, 8, 6, 2, 7, 2, 5, 5, 10, 2
]).pipe(
tap(x => console.log('-------------- 처음 탭: ' + x)),
filter(x => x % 2 === 0),
tap(x => console.log('--------- 필터 후: ' + x)),
distinct(),
tap(x => console.log('중복 제거 후: ' + x)),
).subscribe(x => console.log('발행물: ' + x))
- 통과되는 모든 값마다 특정 작업을 수행
- 발행 결과에 영향을 주지 않음
- 디버깅이나 pipe의 각각 흐음 사이에 콘솔 역할로 사용 할 수 있다.
Transformation 연산자
map Operator
const { of } = rxjs
const { map } = rxjs.operators
of(1, 2, 3, 4, 5).pipe(
map(x => x * x)
).subscribe(console.log)
const { from } = rxjs
const { map } = rxjs.operators
from([
{ name: 'apple', price: 1200 },
{ name: 'carrot', price: 800 },
{ name: 'meat', price: 5000 },
{ name: 'milk', price: 2400 }
]).pipe(
map(item => item.price)
).subscribe(console.log)
- js의 map 함수와 동일
pluck Operator
const { from } = rxjs
const { pluck } = rxjs.operators
const obs$ = from([
{ name: 'apple', price: 1200, info: { category: 'fruit' } },
{ name: 'carrot', price: 800, info: { category: 'vegetable' } },
{ name: 'pork', price: 5000, info: { category: 'meet' } },
{ name: 'milk', price: 2400, info: { category: 'drink' } }
])
obs$.pipe(
pluck('price')
).subscribe(console.log)
obs$.pipe(
pluck('info'),
pluck('category'),
).subscribe(console.log) // info 속성을 뽑고 info안에 category요소를 뽑아서 발행한다.
obs$.pipe(
pluck('info', 'category') // 위와 동일한 동작을 한다. 순서대로 문자열로 넣어주면 된다.
).subscribe(console.log)
const { ajax } = rxjs.ajax
const { pluck } = rxjs.operators
const obs$ = ajax(`https://api.github.com/search/users?q=user:mojombo`).pipe(
pluck('response', 'items', 0, 'html_url')
)
obs$.subscribe(console.log)
- 배열안 객체의 특정 속성만 뽑아서 발행할 때 사용하면 편리하다.
toArray Operator
const { range } = rxjs
const { toArray, filter } = rxjs.operators
range(1, 50).pipe(
filter(x => x % 3 === 0),
filter(x => x % 2 === 1),
toArray()
).subscribe(console.log)
- 연속되는 일련의 값들을 묶어서 배열로 발행한다.
scan Operator
const { of } = rxjs
const { reduce, scan } = rxjs.operators
const obs$ = of(1, 2, 3, 4, 5)
// reduce는 결과만 발행한다.
obs$.pipe(
reduce((acc, x) => { return acc + x }, 0)
).subscribe(x => console.log('reduce: ' + x)) // 15
//과정을 모두 발행한다.
obs$.pipe(
scan((acc, x) => { return acc + x }, 0)
).subscribe(x => console.log('scan: ' + x)) // 1 3 6 10 15
zip Operator
const { from, interval, fromEvent, zip } = rxjs
const { pluck } = rxjs.operators
const obs1$ = from([1, 2, 3, 4, 5])
const obs2$ = from(['a', 'b', 'c', 'd', 'e'])
const obs3$ = from([true, false, 'F', [6, 7, 8], { name: 'zip' }])
zip(obs1$, obs2$).subscribe(console.log) // [1, 'a'], [2, 'b'], [3, 'c'], [4, 'd'], [5, 'e']
const obs1$ = from([1, 2, 3, 4, 5, 6, 7])
const obs4$ = interval(1000)
const obs5$ = fromEvent(document, 'click').pipe(pluck('x'))
zip(obs4$, obs5$).subscribe(console.log)
- 옵저버블을 만드는 연산자이다.
- 인자로 들어온 옵저버블을 각각의 요소들을 묶어서 배열로 발행한다. (같은 index의 있는 요소들을 묶는다.)
- 2개 이상의 옵저버블을 묶어준다.
- 인자로들어온 옵저버블 중에 가장 값이 적은 것에 맞춰서 배열로 발행한다.
Take와 Skip 관련 연산자들
Take 관련 연산자
- interval, fromEvent를 사용할때 스트림은 끝 없이 계속 발행된다.
- 시간이나 이벤트를 다룰 때 take를 사용해서 스트림의 COMPLETE 시점을 정해서 다룰 수 있다.
take : 앞에서부터 N개를 선택한다.
const { range, interval, fromEvent } = rxjs
const { take, filter, pluck } = rxjs.operators
range(1, 20).pipe(
take(5)
).subscribe(console.log) // 1, 2, 3, 4, 5
range(1, 20).pipe(
filter(x => x % 2 === 0),
take(5)
).subscribe(console.log) // 2, 4, 6, 8, 10
interval(1000).pipe(
take(5)
).subscribe(
console.log,
err => console.error(err),
_ => console.log('COMPLETE')
)// 0,1,2,3,4
takeLast : 뒤에서부터 N개를 선택한다.
const { range, interval, fromEvent } = rxjs
const { takeLast, take, pluck } = rxjs.operators
range(1, 20).pipe(
takeLast(5)
).subscribe(console.log) // 20, 19, 18, 17, 16
interval(1000).pipe(
takeLast(5)
).subscribe(
console.log,
err => console.error(err),
_ => console.log('COMPLETE')
)// 발행 안됨
**interval(1000).pipe(
take(10),
takeLast(5)
).subscribe(
console.log,
err => console.error(err),
_ => console.log('COMPLETE')
)// 0 ~ 9 (10초동안) 발행되고 끝났을 때 => 9,8,7,6,5 발행됨**
- 시간이나 이벤트 스트림에서 takeLast만 사용하면 작동하지 않는다. take를 사용해서 언제 끝나는지를 알려주고 완료된 발행 값들 중 뒤에서 N개를 선택한다.
takeWhile : ~하는 동안 선택한다.
const { range, interval, fromEvent } = rxjs
const { takeWhile, takeLast, filter, pluck } = rxjs.operators
range(1, 20).pipe(
takeWhile(x => x <= 10)
).subscribe(console.log) // 1,2,3,4,5,6,7,8,9,10
takeUntil : 기준이 되는 스트림이 발행하기까지
const { interval, timer, fromEvent } = rxjs
const { ajax } = rxjs.ajax
const { takeUntil, pluck, tap } = rxjs.operators
obs1$ = interval(1000)
obs2$ = fromEvent(document, 'click')
obs1$.pipe(
takeUntil(obs2$)
).subscribe(
console.log,
err => console.error(err),
_ => console.log('COMPLETE')
)
- interval이 구독되서 0부터 1초에 차례대로 1씩 증가한 값이 발행되다가 클릭 이벤트가 일어나면 'COMPLETE' 이 출력되고 끝난다.
skip관련 연산자
skip : 앞에서부터 N개 건너뛰기
const { range, interval, fromEvent } = rxjs
const { skip, filter, pluck } = rxjs.operators
range(1, 10).pipe(
skip(5)
).subscribe(console.log) // 6,7,8,9,10
- 1부터 5까지 건너뛰고 뒤에 숫자들이 발행된다.
skipLast : 뒤에서부터 N개 건너뛰기
const { range, interval, fromEvent } = rxjs
const { skipLast, pluck } = rxjs.operators
range(1, 10).pipe(
skipLast(5)
).subscribe(console.log) //1,2,3,4,5
interval(1000).pipe(
skipLast(5)
).subscribe(
console.log,
err => console.error(err),
_ => console.log('COMPLETE')
)// 5초가 지나고 5초전에 발행된 0부터 발행된다. => 5개의 스트림이 밀려서 발행된다.
fromEvent(document, 'click').pipe(
skipLast(5),
pluck('x')
).subscribe(
console.log,
err => console.error(err),
_ => console.log('COMPLETE')
)// 5번의 클릭을 하고나서 처음 클릭한 좌표부터 차례로 발행된다. => 전에 클릭한 x좌표부터 밀려서 발행된다.
- takeLast와는 다르게 시간과 이벤트를 다루는 스트림에서 사용할때 N개(초) 값을 미뤄서 발행한다.
skipWhile : ~하는 동안 건너뛰기
const { range, interval, fromEvent } = rxjs
const { skipWhile, filter, pluck } = rxjs.operators
range(1, 20).pipe(
skipWhile(x => x <= 10)
).subscribe(console.log) // 11,12,13,14,15,16,17,18,19,20
- 10보다 작거나 같을때까지 건너뛰고 나머지 숫자 발행
skipUntil : 기준이 되는 스트림이 발행하고부터
const { interval, timer, fromEvent } = rxjs
const { skipUntil, pluck } = rxjs.operators
const obs1$ = interval(1000)
const obs2$ = fromEvent(document, 'click')
obs1$.pipe(
skipUntil(obs2$)
).subscribe(
console.log,
err => console.error(err),
_ => console.log('COMPLETE')
)
- 클릭 이벤트가 일어났을 때 해당하는 숫자부터 발행된다.
반응형