Last active
November 18, 2018 10:59
-
-
Save kyungmi/7c77e21e52877c0dff6f7a465b9123cd to your computer and use it in GitHub Desktop.
RxJS 퀵스타트 8장
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { fromEvent } = rxjs; | |
const { switchMap, takeUntil } = rxjs.operators; | |
const view = document.getElementById('carousel'); | |
const start$ = fromEvent(view, 'mousedown'); | |
const move$ = fromEvent(view, 'mousemove'); | |
const end$ = fromEvent(view, 'mouseup'); | |
const drag$ = start$.pipe( | |
// Observable을 평탄하게 합치기 위해 mergeMap을 사용할 수 있으나 | |
// start$에서 데이터가 발생할 때마다 move$가 생성되므로 기존 데이터를 자동으로 종료하기 위해 switchMap을 사용한다. | |
switchMap(start => move$.pipe( | |
// takeUntil에 전달된 end$ Observable에서 데이터가 발생하는 순간 대상의 상태를 종료 처리하고 자동으로 구독을 해제한다. | |
takeUntil(end$), | |
)), | |
); | |
drag$.subscribe(e => console.log(e)); | |
// MouseEvent {isTrusted: true, screenX: 1074, screenY: 551, clientX: 163, clientY: 106, …} | |
// MouseEvent {isTrusted: true, screenX: 1101, screenY: 548, clientX: 190, clientY: 104, …} | |
// MouseEvent {isTrusted: true, screenX: 1130, screenY: 548, clientX: 219, clientY: 104, …} | |
// MouseEvent {isTrusted: true, screenX: 1163, screenY: 548, clientX: 252, clientY: 104, …} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { fromEvent } = rxjs; | |
const { switchMap, takeUntil, map } = rxjs.operators; | |
const view = document.getElementById('carousel'); | |
// Observable을 받아 Observable을 반환하는 오퍼레이터를 만듬 | |
const toPos = (obs$) => obs$.pipe(map(e => e.pageX)); | |
const start$ = fromEvent(view, 'mousedown').pipe(toPos); | |
const move$ = fromEvent(view, 'mousemove').pipe(toPos); | |
const end$ = fromEvent(view, 'mouseup').pipe(toPos); | |
const drag$ = start$.pipe( | |
switchMap(startX => move$.pipe( | |
// 처음 X 좌표에서 이동한 거리를 반환 | |
map(moveX => moveX - startX), | |
takeUntil(end$), | |
)), | |
); | |
drag$.subscribe(v => console.log(v)); | |
// 1 | |
// 2 | |
// 5 | |
// 10 | |
// 15 | |
// 25 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* drag$ Observable에서 데이터가 발생한 순간부터 end$ Observable의 데이터가 **딱 한번** 발생한 경우가 drop$이다. | |
*/ | |
const { take, first } = rxjs.operators; | |
const drop$ = drag$.pipe( | |
// 기존 Observable을 자동 종료하기 위해서 switchMap 사용 | |
// switchMap 대신 mergeMap을 사용하면 Observer에서 동일 데이터를 drag$ observable 이벤트 개수만큼 발생시킨다. | |
switchMap(dragX => end$.pipe(take(1))), | |
// switchMap(dragX => end$.pipe(first())), | |
); | |
drop$.subscribe(v => console.log(v)); | |
// 341 |
- 직접적으로 구독을 해제(
unsubscribe
)하지 않는다. 가급적이면takeUntil
,take
,first
오퍼레이터를 사용해 자동으로 구독을 해제하도록 한다.
take
: end$에 take operator를 적용하여 end$의 데이터가 딱 한 번 발생할때 end$ 데이터 발생을 중지시킨다.first
: 인자가 없는 경우take(1)
과 같지만, 첫 번째 인자로 조건 함수를 전달받을 수 있어서 데이터를 조건별로 분류할 수 있다.
const click$ = fromEvent(document, 'click').pipe(
first(ev => ev.target.tagName === 'DIV'),
);
-
startWith
- http://rxmarbles.com/#startWith
- 구독 시에 바로 전달할 초깃값
-
withLatestFrom
- http://rxmarbles.com/#withLatestFrom
- A라는 Observable 데이터가 발생했을 시 B, C, ...Observable의 최신 데이터를 함께 전달받을 수 있게 해준다.
withLatestFrom
은 전달한 Observable에서 데이터가 발생하지 않으면 원래 Observable도 반환하지 않는다.- 마지막 인자로 함수를 전달하지 않으면 배열로 값들이 전달된다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { fromEvent } = rxjs; | |
const { map, withLatestFrom, switchMap, startWith } = rxjs.operators; | |
const viewWidth$ = fromEvent(window, 'resize').pipe( | |
// 구독시에 초기값을 전달 (필수) | |
// `withLatestFrom`은 전달받은 Observable에서 데이터가 발생하지 않으면 원래 Observable도 반환하지 않는다. | |
startWith(0), | |
map(() => view.clientWidth), | |
); | |
const drop$ = drag$.pipe( | |
switchMap(dragX => end$.pipe(first())), | |
// drop$ 이벤트가 발생하는 시점에 size$의 최신 값을 전달받음 | |
withLatestFrom(viewWidth$), | |
); | |
drop$.subscribe(([drogX, viewWidth]) => console.log([drogX, viewWidth])); | |
// (2) [110, 865] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { fromEvent } = rxjs; | |
const { map } = rxjs.operators; | |
const viewWidth$ = fromEvent(window, 'resize').pipe( | |
map(() => view.clientWidth), | |
); | |
viewWidth$.subscribe(width => console.log('view의 넓이', width); |
- drag$ Observable은 Cold Observable은 완전히 독립적인 영역을 갖고 있어 구독하는 Observer마다 별개의 데이터를 전달한다.
- 데이터는 drag일때도, drop일때도 중복 발생한다.
- drag$를 공유자원으로 만들면 drag$, drop$이 각각 한 번씩 발생한다.
- 음? 두 번씩 안 발생하는데❓
- 지금 보니 8.6에서 merge로 drag$, drop$을 합쳤을때 두 번씩 발생하게 되는 것 같다.
- 참고: https://codepen.io/kyungmi-the-bold/pen/yQowLW/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { merge } = rxjs; | |
const carousel$ = merge(drag$, drop$); | |
carousel$.subscribe(v => console.log('캐러셀 데이터', v); |
- drag & drop을 구현하는 또 다른 방법: https://medium.com/@jdjuan/mouse-drag-with-rxjs-45861c4d0b7e
skipUntil
,takeUntil
사용
import { paint } from './canvas.js';
const { fromEvent } = Rx.Observable;
const { skipUntil, takeUntil } = Rx.operators;
const move$ = fromEvent(document, 'mousemove');
const down$ = fromEvent(document, 'mousedown')
const up$ = fromEvent(document, 'mouseup')
const paints$ = move$.pipe(
skipUntil(down$),
takeUntil(up$)
);
paints$.subscribe(paint);
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment