CODE

[ReactiveX]Operator 종류와 사용법

기본적인 배열 연산자

산수 관련 연산자

count

배열의 개수를 카운트하는 연산자.

const { of } = rxjs
const { count } = rxjs.operators

const obs$ = of(4, 2, 6, 10, 8)

obs$.pipe(count()).subscribe(x => console.log('count: ' + x)) // count: 5

 

max

배열의 최대 값을 찾아내는 연산자.

const { of } = rxjs
const { max } = rxjs.operators

const obs$ = of(4, 2, 6, 10, 8)

obs$.pipe(max()).subscribe(x => console.log('max: ' + x)) // max: 10

min

배열의 최소 값을 찾아내는 연산자.

const { of } = rxjs
const { max } = rxjs.operators

const obs$ = of(4, 2, 6, 10, 8)

obs$.pipe(max()).subscribe(x => console.log('max: ' + x)) // min: 2

reduce

누적된 값을 반환해주는 연산자.

const { of } = rxjs
const { max } = rxjs.operators

const obs$ = of(4, 2, 6, 10, 8)

obs$.pipe(
    reduce((acc, x) => { return acc + x }, 0)
).subscribe(x => console.log('reduce: ' + x)) // reduce: 30

 

누적되는 연산

acc      x      result

0    +   4    =  4

4    +   2    =  6

6    +   6    =  12

12   +   10    = 22

22   +   8    =  30

선택 관련 연산자

first

배열의 첫번째 값을 선택해주는 연산자.

const { from } = rxjs
const { first } = 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)) // first: 9

last

배열의 마지막 값을 선택해주는 연산자.

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(last()).subscribe(x => console.log('last: ' + x)) // last: 2

elementAt

배열의 n번째 값을 선택해주는 연산자.

const { from } = rxjs
const { elementAt } = 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(elementAt(5)).subscribe(x => console.log('elementAt: ' + x)) // elementAt: 10

distinct

배열의 중복된 값을 제외하여 선택해주는 연산자.

const { from } = rxjs
const { 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(distinct()).subscribe(x => console.log('distinct: ' + x)) // distinct: 9 10 5 1 4 8

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(
    filter(x => x % 2 === 1)
).subscribe(x => console.log('filter: ' + x)) //  filter: 9 3 5 1 9 9 1 1 7 5 5

 

tap 연산자

로그를 반환해주는 연산자. 데이터를 가공하는 연산자를 사용하기 전에 원래 데이터를 표시하기 위한 용도로 사용할 수 있다.

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

————– 처음 탭: 9
————– 처음 탭: 3
————– 처음 탭: 10
——— 필터 후: 10
중복 제거 후: 10
발행물: 10
————– 처음 탭: 5
————– 처음 탭: 1
————– 처음 탭: 10
——— 필터 후: 10
————– 처음 탭: 9
————– 처음 탭: 9
————– 처음 탭: 1
————– 처음 탭: 4
——— 필터 후: 4
중복 제거 후: 4
발행물: 4
————– 처음 탭: 1
————– 처음 탭: 8
——— 필터 후: 8
중복 제거 후: 8
발행물: 8
————– 처음 탭: 6
——— 필터 후: 6
중복 제거 후: 6
발행물: 6
————– 처음 탭: 2
——— 필터 후: 2
중복 제거 후: 2
발행물: 2
————– 처음 탭: 7
————– 처음 탭: 2
——— 필터 후: 2
————– 처음 탭: 5
————– 처음 탭: 5
————– 처음 탭: 10
——— 필터 후: 10
————– 처음 탭: 2
——— 필터 후: 2

예제

1. 짝수들 중에서 가장 큰 수

const { from } = rxjs
const { filter, max } = 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(
    filter(x => x % 2 === 0),
    max()
).subscribe(x => console.log(x)) // 10

2. 5보다 큰 3번째 짝수

const { from } = rxjs
const { elementAt, filter } = 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(
    filter(x => x > 5 && x % 2 === 0), 
    elementAt(2)
).subscribe(x => console.log(x)) // 8

3. 한 번 이상 나온 홀수들의 갯수, 합

const { from } = rxjs
const { reduce, first, last, elementAt, filter, distinct, max, count } = 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(
    distinct(),
    filter(x => x % 2 === 1), 
//  count() // 5
    reduce((acc, cur) => acc + cur, 0) // 25
).subscribe(x => console.log(x)) 

 

Transformation 연산자

map 연산자

스트림으로 들어오는 값을 익명 함수로 받아 일정한 연산을 하고자 할 때 사용하는 연산자. 단순 데이터뿐만 아니라 오브젝트로 된 데이터에서도 사용할 수 있다.

const { of } = rxjs
const { map } = rxjs.operators

of(1, 2, 3, 4, 5).pipe(
    map(x => x * x)
).subscribe(console.log) // 1 4 9 16 25
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) // 1200 800 5000 2400

pluck 연산자

객체 안의 특정 키의 값만 뽑아오는 연산자.

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) // 1200 800 5000 2400
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('info', 'category')
//    pluck('info'),
//    pluck('category')
).subscribe(console.log) // fruit vegetable meet drink

 

ajax 요청과 함께 사용하기
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) // https://github.com/mojombo

toArray 연산자

연속되는 일련의 값들을 하나의 배열로 묶어서 반환해주는 연산자.

toArray() 연산자를 사용하지 않은 경우

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

3
9
15
21
27
33
39
45

toArray() 연산자를 사용한 경우

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)
<console>
[3, 9, 15, 21, 27, 33, 39, 45]

scan 연산자

연속적인 연산을 할 때 중간 과정을 스캔해서 보여주는 연산자.

결과만 발행할 경우

const { of } = rxjs
const { reduce, scan } = rxjs.operators

const obs$ = of(1, 2, 3, 4, 5)

obs$.pipe(
    reduce((acc, x) => { return acc + x }, 0)
).subscribe(x => console.log('reduce: ' + x))
<console>

reduce: 15

과정을 모두 발행할 경우

const { of } = rxjs
const { reduce, scan } = rxjs.operators

const obs$ = of(1, 2, 3, 4, 5)

obs$.pipe(
    scan((acc, x) => { return acc + x }, 0)
).subscribe(x => console.log('scan: ' + x))
<console>

scan: 1
scan: 3
scan: 6
scan: 10
scan: 15

zip 연산자

두개 이상의 배열을 최소 배열 수에 맞춰 각각의 Index 끼리 묶어 새로운 배열을 만들어주는 연산자. 다른 연산자와 달리 rxjs.operate 가 아닌 rxjs에서 임포트해서 사용한다.

const { from, interval, fromEvent, zip } = rxjs
const { pluck } = rxjs.operators

const obs1$ = from([1, 2, 3, 4, 5])
// const obs1$ = from([1, 2, 3, 4, 5, 6, 7]) 배열의 개수가 늘어나도 합치는 배열 중에 가장 작은 배열에 맞춰 발행된다.
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)
<console>
[1, “a”] [2, “b”] [3, “c”] [4, “d”] [5, “e”]

interval과 formEvent 옵져버블 zip하기

1초에 한번씩 발행하는 옵져버블 obs4$과 클릭된 값을 발행하는 옵져버블 obs5$를 zip하여 값이 쌓이지 않았을 때는 log가 출력되지 않는 것을 확인할 수 있다.

const { from, interval, fromEvent, zip } = rxjs
const { pluck } = rxjs.operators

const obs1$ = from([1, 2, 3, 4, 5, 6, 7])
const obs2$ = from(['a', 'b', 'c', 'd', 'e'])
const obs3$ = from([true, false, 'F', [6, 7, 8], { name: 'zip' }])

const obs4$ = interval(1000)
const obs5$ = fromEvent(document, 'click').pipe(pluck('x'))

zip(obs4$, obs5$).subscribe(console.log)

take와 skip 관련 연산자

take 연산자

배열의 앞에서 n개 선택해주는 연산자.

const { range, interval, fromEvent } = rxjs
const { take, filter, pluck, toArray } = rxjs.operators

range(1, 20).pipe(
    take(5),
    toArray()
).subscribe(console.log) // [1, 2, 3, 4, 5]

interval과 함께 사용하기

take를 지정하지 않으면 0부터 계속해서 1씩 늘어나는데 이를 take(5)를 지정해서 5개까지만 발행하도록 만들 수 있다.

const { range, interval, fromEvent } = rxjs
const { take, filter, pluck, toArray } = rxjs.operators

interval(1000).pipe(
    take(5)
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)
<console>

0
1
2
3
4
“COMPLETE”

fromEvent와 함께 사용하기

take를 지정하지 않으면 클릭 이벤트로 받은 값을 계속해서 발행하는데 take(5)를 지정해서 5개까지만 발행하도록 만들 수 있다.

const { range, interval, fromEvent } = rxjs
const { take, filter, pluck, toArray } = rxjs.operators

fromEvent(document, 'click').pipe(
    take(5),
    pluck('x')
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)
<console>

273
387
359
172
471
“COMPLETE”

takeLast 연산자

배열의 뒤에서 n개 선택해주는 연산자.

const { range, interval, fromEvent } = rxjs
const { takeLast, take, pluck, toArray } = rxjs.operators

range(1, 20).pipe(
    takeLast(5),
    toArray()
).subscribe(console.log) // [16, 17, 18, 19, 20]

interval과 함께 사용하기

last 값을 알지 못하는 상태에서는 값을 발행해주지 못하지만 10초 후에 take(10)로 발행할 값을 10개로 한정시킨 상태에서는 마지막 값을 알 수 있게 되기 때문에 10초 후에 마지막 값 5개가 출력될 수 있다.

const { range, interval, fromEvent } = rxjs
const { takeLast, take, pluck, toArray } = rxjs.operators

interval(1000).pipe(
    take(10),
    takeLast(5),
    toArray()
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

// [5, 6, 7, 8, 9]
// COMPLETE

fromEvent와 함께 사용하기

last 값을 알지 못하는 상태에서는 값을 발행해주지 못하지만 10번 클릭한 후에 발행할 값을 10개로 한정시킨 상태에서는 마지막 값을 알 수 있게 되기 때문에 10초 후에 마지막 값 5개가 출력될 수 있다.

const { range, interval, fromEvent } = rxjs
const { takeLast, take, pluck, toArray } = rxjs.operators

fromEvent(document, 'click').pipe(
    take(10),
    takeLast(5),
    pluck('x'),
    toArray()
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

// [287, 424, 403, 379, 192]
// COMPLETE

takeWhile 연산자

특정 조건에 만족하는 동안 값을 발행하는 연산자.

const { range, interval, fromEvent } = rxjs
const { takeWhile, takeLast, filter, pluck, toArray } = rxjs.operators

range(1, 20).pipe(
    takeWhile(x => x <= 10),
    toArray()
).subscribe(console.log) 

// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

interval과 함께 사용하기

1초에 한번씩 5보다 값이 작을때까지의 값을 다 발행하고 나면 자동으로 complete 된다.

const { range, interval, fromEvent } = rxjs
const { takeWhile, takeLast, filter, pluck, toArray } = rxjs.operators

interval(1000).pipe(
    takeWhile(x => x < 5),
    toArray()
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

// [0, 1, 2, 3, 4] 
// COMPLETE

fromEvent와 함께 사용하기

클릭된 값을 저장하고 있다가 200보다 작은 부분을 클릭했을 때 쌓인 값을 모두 발행하고 자동으로 complete 된다.

const { range, interval, fromEvent } = rxjs
const { takeWhile, takeLast, filter, pluck, toArray } = rxjs.operators

fromEvent(document, 'click').pipe(
    pluck('x'),
    takeWhile(x => x < 200),
    toArray()
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

// [189, 77]
// COMPLETE 

takeUntil 연산자

기준이 되는 옵져버블이 발행될 때 complete 시키는 연산자.

interval와 fromEvent 함께 사용하기

click 이벤트로 takeUntil하기

1초에 1씩 늘어나는 숫자를 발행하고 있다가 클릭하는 순간 complete 된다.

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')
)
<console>

0
1
2
3
4
5
6
7
COMPLETE

interval로 takeUntil하기

클릭을 계속 발행하다가 5초가 지나는 순간 complete 한다.

const { interval, timer, fromEvent } = rxjs
const { ajax } = rxjs.ajax
const { takeUntil, pluck, tap } = rxjs.operators

obs1$ = fromEvent(document, 'click')
obs2$ = timer(5000)

obs1$.pipe(
    pluck('x'),
    takeUntil(obs2$)
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)
<console>

254
375
321
171
517
596
COMPLETE

ajax 활용하기

ajax로 값을 불러오기까지 특정 코드를 실행해야할 경우 사용할 수 있다. 예를 들어 ajax 요청을 기다리는 동안 애니메이션을 구현할 수 있다.

const { interval, timer, fromEvent } = rxjs
const { ajax } = rxjs.ajax
const { takeUntil, pluck, tap } = rxjs.operators

interval(50).pipe(
    takeUntil(
        ajax('http://127.0.0.1:3000/people/name/random').pipe(
            pluck('response'),
            tap(console.log)
        )
    )
).subscribe(console.log)
<console>

0
1
2
3
4
5
6

{
{“id”:26,
“first_name”:”Naomi”,
“last_name”:”Taylor”,
“sex”:”female”,
“blood_type”:”O”,
“serve_years”:5,
“role”:”developer”,
“team”:4,
“from”:”Oklahoma”
}
}

skip 연산자

배열의 앞에서 n개 건너띄어주는 연산자.

const { range, interval, fromEvent } = rxjs
const { take, filter, pluck, toArray } = rxjs.operators

range(1, 20).pipe(
    take(5),
    toArray()
).subscribe(console.log) // [1, 2, 3, 4, 5]

interval과 함께 사용하기

0부터 계속해서 1씩 늘어나는 옵져버블을 발행하는데 앞에서부터 5개를 skip하고 발행한다

const { range, interval, fromEvent } = rxjs
const { skip, filter, pluck, toArray } = rxjs.operators

interval(1000).pipe(
    skip(5),
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
) 
<console>

5
6
7
8
9
10
11
12

fromEvent와 함께 사용하기

클릭된 값을 발행하는데 여기서 5번 클릭까지는 skip하고 발행한다.

const { range, interval, fromEvent } = rxjs
const { skip, filter, pluck, toArray } = rxjs.operators

fromEvent(document, 'click').pipe(
    skip(5),
    pluck('x')
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)
<console>

212
467
446
246

skipLast 연산자

배열의 뒤에서 n개를 건너띄어주는 연산자.

const { range, interval, fromEvent } = rxjs
const { skipLast, pluck, toArray } = rxjs.operators

range(1, 20).pipe(
    skipLast(5),
    toArray()
).subscribe(console.log) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

interval과 함께 사용하기

1초에 1씩 늘어나는 옵져버블에서 5개까지는 skip하기 때문에 아무것도 발행하지 않다가 6개 값부터 현재까지 나온 값에서 마지막 5개를 스킵하고 발행한다. 즉, 첫번째 값부터 차례대로 발행된다.

const { range, interval, fromEvent } = rxjs
const { takeLast, take, pluck, toArray } = rxjs.operators

interval(1000).pipe(
    take(10),
    takeLast(5),
    toArray()
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

<console>

0
1
2
3
4
5
6
7
8
9
10

fromEvent와 함께 사용하기

클릭한 값 5개까지는 skip하기 때문에 아무것도 발행하지 않다가 6개 값부터 현재까지 나온 값에서 마지막 5개를 스킵하고 발행한다. 즉, 첫번째 값부터 차례대로 발행된다.

const { range, interval, fromEvent } = rxjs
const { skipLast, pluck, toArray } = rxjs.operators

fromEvent(document, 'click').pipe(
    skipLast(5),
    pluck('x')
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

skipWhile 연산자

특정 조건에 만족하는 동안 값을 건너띄는 연산자.

const { range, interval, fromEvent } = rxjs
const { skipWhile, filter, pluck, toArray } = rxjs.operators

range(1, 20).pipe(
    skipWhile(x => x <= 10),
    toArray()
).subscribe(console.log) // [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

interval과 함께 사용하기

1초에 1씩 늘어나는 옵져버블에서 값이 5보다 작은 값을 스킵하고 발행한다.

const { range, interval, fromEvent } = rxjs
const { skipWhile, filter, pluck, toArray } = rxjs.operators

interval(1000).pipe(
    skipWhile(x => x < 5)
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

fromEvent와 함께 사용하기

클릭된 값을 출력하다가 200보다 작은 부분을 클릭했을 때의 값은 스킵해준다.

const { range, interval, fromEvent } = rxjs
const { skipWhile, filter, pluck, toArray } = rxjs.operators

fromEvent(document, 'click').pipe(
    pluck('x'),
    skipWhile(x => x < 200),
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)

takeUntil 연산자

기준이 되는 옵져버블이 발행되었을 때

interval와 fromEvent 함께 사용하기

click 이벤트로 skipUntil하기

1초에 1씩 늘어나는 값을 스킵하고 있다가 클릭하는 순간부터 발행하기 시작한다.

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')
)
<console>

3
4
5
6
7
8
9
10
11

interval로 takeUntil하기

클릭한 값을 스킵하고 5초가 지나는 순간 발행하기 시작한다.

const { interval, timer, fromEvent } = rxjs
const { skipUntil, pluck } = rxjs.operators

const obs1$ = fromEvent(document, 'click')
const obs2$ = timer(5000)

obs1$.pipe(
    pluck('x'),
    skipUntil(obs2$)
).subscribe(
    console.log,
    err => console.error(err),
    _ => console.log('COMPLETE')
)
<console>

254
375
321
171
517
596
COMPLETE

시간을 다루는 연산자

delay()

주어진 시간만큼 발행을 지연시키는 연산자.

interval과 함께 사용하기
const { interval, fromEvent } = rxjs
const { delay, tap, take } = rxjs.operators

interval(1000).pipe(
    take(5),
    tap(x => console.log(x + ' 발행시작')),
    delay(5000)
).subscribe(x => console.log(x + ' 발행완료'))
<console>

0 발행시작
1 발행시작
2 발행시작
3 발행시작
4 발행시작
0 발행완료
1 발행완료
2 발행완료
3 발행완료
4 발행완료

formEvent와 함께 사용하기
const { interval, fromEvent } = rxjs
const { delay, tap, take } = rxjs.operators

fromEvent(document, 'click').pipe(
    tap(e => console.log(e.x + ' 발행시작')),
    delay(5000)
).subscribe(e => console.log(e.x + ' 발행완료'))
<console>

207 발행시작
207 발행완료
278 발행시작
427 발행시작
278 발행완료
427 발행완료

timestamp()

발행된 시간을 함께 발행해 주는 연산자.

formEvent와 함께 사용하기
const { fromEvent } = rxjs
const { timestamp, pluck, map } = rxjs.operators

fromEvent(document, 'click').pipe(
    pluck('x'),
    timestamp(),
    
    // 타임스탬프를 우리가 알아볼 ㅜ 있는 시간으로 변환
    map(x => {
        x.timestamp = new Date(x.timestamp).toString()
        return x
    })
).subscribe(console.log)
<console>

{
timestamp: “Sun Jun 12 2022 09:37:49 GMT+0900 (KST)”,
value: 339
}
{
timestamp: “Sun Jun 12 2022 09:37:50 GMT+0900 (KST)”,
value: 481
}
{
timestamp: “Sun Jun 12 2022 09:37:51 GMT+0900 (KST)”,
value: 523
}
{
timestamp: “Sun Jun 12 2022 09:37:52 GMT+0900 (KST)”,
value: 460
}

timeinterval()

이전 발행물과의 시간차를 발행해주는 연산자.

interval과 함께 사용하기
const { fromEvent, interval } = rxjs
const { timeInterval, pluck } = rxjs.operators

interval(1000).pipe(
    timeInterval()
).subscribe(console.log)
<console>

{
interval: 1002,
value: 0
}
{
interval: 1000,
value: 1
}
{
interval: 1000,
value: 2
}
{
interval: 1002,
value: 3
}
{
interval: 1000,
value: 4
}
{
interval: 1001,
value: 5
}

formEvent와 함께 사용하기
const { fromEvent, interval } = rxjs
const { timeInterval, pluck } = rxjs.operators

fromEvent(document, 'click').pipe(
    pluck('x'),
    timeInterval()
).subscribe(console.log)
<console>

{
interval: 2329,
value: 173
}
{
interval: 290,
value: 194
}
{
interval: 135,
value: 193
}
{
interval: 1092,
value: 230
}
{
interval: 1020,
value: 371
}

timeout()

주어진 시간 내에 값을 발행하지 않을 때 오류를 만들어주는 연산자.

formEvent와 함께 사용하기
const { fromEvent } = rxjs
const { ajax } = rxjs.ajax
const { timeout, pluck } = rxjs.operators

fromEvent(document, 'click').pipe(
    timeout(3000)
).subscribe(
    _ => console.log('OK'),
    err => console.error(err))
console

“OK”
“OK”
<a class=’gotoLine’ href=’#[object Object’>[object Object</a> {
message: “Timeout has occurred”,
name: “TimeoutError”
}]

ajax와 함께 사용하기
const { fromEvent } = rxjs
const { ajax } = rxjs.ajax
const { timeout, pluck } = rxjs.operators

ajax('http://127.0.0.1:3000/people/name/random').pipe(
    pluck('response'),
    timeout(500)
).subscribe(console.log, console.error)

서버에 요청했을 때 특정 시간 내에 응답을 받지 못할 경우 에러를 만들 수 있다.

timeoutwith()

주어진 시간 내에 값을 발행하지 않을 때 대신할 옵져버블을 발행해주는 연산자

const { fromEvent, interval, of } = rxjs
const { ajax } = rxjs.ajax
const { timeoutWith, pluck, scan } = rxjs.operators

fromEvent(document, 'click').pipe(
    timeoutWith(3000, interval(1000)),
    scan((acc, x) => { return acc + 1 }, 0)
).subscribe(console.log)
ajax와 함께 사용하기
const { fromEvent, interval, of } = rxjs
const { ajax } = rxjs.ajax
const { timeoutWith, pluck, scan } = rxjs.operators

ajax('http://127.0.0.1:3000/people/name/random').pipe(
    pluck('response'),
    timeoutWith(500, of({
        id: 0,
        first_name: 'Hong',
        last_name: 'Gildong',
        role: 'substitute'
    }))
).subscribe(console.log, console.error)

 

deboundceTime()

특정 시간이 경과한 후에 발행시켜주는 연산자. 키보드 입력을 받아 연관 검색어를 띄워주는 코드에서 입력을 받을 때마다 새로운 목록을 가져올 때 사용하면 컴퓨터 자원 낭비를 막을 수 있다.

const { fromEvent } = rxjs
const { timeInterval, pluck, scan, tap } = rxjs.operators

const clicks$ = fromEvent(document, 'click').pipe(
    timeInterval(),
    pluck('interval'),
    scan((acc, i) => acc + i, 0),
    tap(x => console.log('CLICKED: ' + x))
)

const { debounceTime } = rxjs.operators

clicks$.pipe(
    debounceTime(1000)
).subscribe(x => console.log('OUTPUT: -------- ' + x))
console

CLICKED: 943
CLICKED: 1438
CLICKED: 1848
CLICKED: 2197
OUTPUT: ——– 2197
CLICKED: 3524
CLICKED: 3939
CLICKED: 4296
CLICKED: 4610
OUTPUT: ——– 4610

클릭을 게속 하다가 1초동안 클릭을 하지 않으면 OUTPUT이 발행되죠.

auditTime()

특정 시간 동안 발행을 무시하고 마지막 값을 발행하는 연산자.

const { fromEvent } = rxjs
const { timeInterval, pluck, scan, tap } = rxjs.operators

const clicks$ = fromEvent(document, 'click').pipe(
    timeInterval(),
    pluck('interval'),
    scan((acc, i) => acc + i, 0),
    tap(x => console.log('CLICKED: ' + x))
)

const { auditTime } = rxjs.operators

clicks$.pipe(
    auditTime(1000)
).subscribe(x => console.log('OUTPUT: -------- ' + x))
console

CLICKED: 1955
CLICKED: 2197
CLICKED: 2611
CLICKED: 2862
OUTPUT: ——– 2862
CLICKED: 3168
CLICKED: 3901
OUTPUT: ——– 3901
CLICKED: 4528
CLICKED: 5277
OUTPUT: ——– 5277
CLICKED: 5539
CLICKED: 5893
OUTPUT: ——– 5893

sampleTime()

특정 시간 내에 마지막 값을 발행하는 연산자.

const { fromEvent } = rxjs
const { timeInterval, pluck, scan, tap } = rxjs.operators

const clicks$ = fromEvent(document, 'click').pipe(
    timeInterval(),
    pluck('interval'),
    scan((acc, i) => acc + i, 0),
    tap(x => console.log('CLICKED: ' + x))
)

const { sampleTime } = rxjs.operators

clicks$.pipe(
    sampleTime(1000),
    timeInterval()
).subscribe(x => console.log('OUTPUT: -------- ' + x.value + ' :' + x.interval))
console

CLICKED: 3407
CLICKED: 3687
OUTPUT: ——– 3687 :4004
CLICKED: 4099
CLICKED: 4787
OUTPUT: ——– 4787 :1001
CLICKED: 5296
CLICKED: 5856
CLICKED: 5992
OUTPUT: ——– 5992 :1001
CLICKED: 6343
OUTPUT: ——– 6343 :1001

throttleTime()

값이 전송된 후 특정 시간동안 무시하다가 첫번째 값 혹은 마지막 값을 발행할 수 있는 연산자.

const { fromEvent } = rxjs
const { timeInterval, pluck, scan, tap } = rxjs.operators

const clicks$ = fromEvent(document, 'click').pipe(
    timeInterval(),
    pluck('interval'),
    scan((acc, i) => acc + i, 0),
    tap(x => console.log('CLICKED: ' + x))
)

const { throttleTime } = rxjs.operators

clicks$.pipe(
    throttleTime(1000, undefined, { 
    	leading: true, trailing: false 
    })
).subscribe(x => console.log('OUTPUT: -------- ' + x))

leading : true 처음에 발행한 값을 무조건 발행

trailing : true 마지막에 발행한 값을 무조건 발행

undefined Rxjs의 스케줄러 옵션을 생략

trailing : true 로 발행하면 auditTime과 비슷하게 발행되는데 마지막에 comlete 시 마지막 값을 출력하는지 안하는지의 차이가 있습니다.
console

CLICKED: 3407
CLICKED: 3687
OUTPUT: ——– 3687 :4004
CLICKED: 4099
CLICKED: 4787
OUTPUT: ——– 4787 :1001
CLICKED: 5296
CLICKED: 5856
CLICKED: 5992
OUTPUT: ——– 5992 :1001
CLICKED: 6343
OUTPUT: ——– 6343 :1001

스트림을 결합하는 연산자

merge()

두가지 이상의 스트림을 순서에 상관없이 하나로 결합하는 연산자.

const { merge, interval, fromEvent } = rxjs
const { map } = rxjs.operators

const interval$ = interval(1000).pipe(map(_ => 'interval'))
const click$ = fromEvent(document, 'click').pipe(map(_ => 'click'))

merge(interval$, click$).subscribe(console.log)
<console>

interval
click
interval
click
click
click
click
interval
interval
interval
interval

마지막 인자로 숫자를 넣으면 해당 숫자만큼씩만 발행합니다.

concat()

두가지 이상의 스트림을 순서대로 결합하는 연산자.

const { concat, interval } = rxjs
const { map, take } = rxjs.operators

const intv1$ = interval(1000).pipe(
    map(_ => 'INTERVAL 1'), take(3))
const intv2$ = interval(1000).pipe(
    map(_ => 'INTERVAL 2'), take(3))
const intv3$ = interval(1000).pipe(
    map(_ => 'INTERVAL 3'), take(3))

concat(intv1$, intv2$, intv3$)
.subscribe(console.log)
<console>

INTERVAL 1
INTERVAL 1
INTERVAL 1
INTERVAL 2
INTERVAL 2
INTERVAL 2
INTERVAL 3
INTERVAL 3
INTERVAL 3

mergeMap()

하나의 옵져블에서 파생된 스티림들을 순서에 상관없이 하나로 결합하는 연산자.

const { interval, fromEvent } = rxjs
const { mergeMap, map, take } = rxjs.operators

fromEvent(document, 'click').pipe(
    mergeMap(e => interval(1000).pipe(
        map(i => e.x + ' : ' + i),
        take(5)
    ))
).subscribe(console.log)
<console>

370 : 0
370 : 1
370 : 2
370 : 3
370 : 4
373 : 0
373 : 1
373 : 2
373 : 3
501 : 0
373 : 4
501 : 1
501 : 2
501 : 3
501 : 4

concatMap()

하나의 옵져버블에서 파생된 스트림들을 순서대로 결합하는 연산자.

const { interval, fromEvent } = rxjs
const { concatMap, map, take } = rxjs.operators

fromEvent(document, 'click').pipe(
    concatMap(e => interval(1000).pipe(
        map(i => e.x + ' : ' + i),
        take(5)
    ))
).subscribe(console.log)
<console>

259 : 0
259 : 1
259 : 2
259 : 3
259 : 4
408 : 0
408 : 1
408 : 2
408 : 3
408 : 4
587 : 0
587 : 1
587 : 2

switchMap()

다음 스트림을 발행하면 이전 스트림을 끊어내고 발행하는 연산자.

const { interval, fromEvent } = rxjs
const { switchMap, map, take } = rxjs.operators

fromEvent(document, 'click').pipe(
    switchMap(e => interval(1000).pipe(
        map(i => e.x + ' : ' + i),
        take(5)
    ))
).subscribe(console.log)
<console>

439 : 0
439 : 1
439 : 2
348 : 0
348 : 1
348 : 2
344 : 0
344 : 1
344 : 2
344 : 3
344 : 4

~MapTo()

mergeMapTo(), concatMapTo(), switchMapTo() 두번쨰 스트림으로만 발행하고 싶을 때 사용하는 연산자.

최신글