home강의 홈으로
Section 3. 실전 RxJS!
Lesson 1. 스마트한 키워드 검색창 만들기
<script src="https://unpkg.com/@reactivex/rxjs/dist/global/rxjs.umd.js"></script>
<input id='keyword' type='text' />
<br>
<div id='result'></div>
body {
padding: 12px;
font-family: sans-serif
}
#keyword {
width: 200px; height: 24px; line-height: 24px;
margin-bottom: 8px; padding: 2px 8px;
border: 2px solid #ccc;
border-radius: 4px;
}
#result {
width: 200px;
}
#result article {
width: 192px; height: 30px; line-height: 30px;
padding: 0 12px;
border: 1px solid #ddd;
background-color: #f5f5f5;
cursor: pointer;
}
#result article:not(:last-child) { border-bottom: 0; }
#result article:first-child { border-radius: 4px 4px 0 0; }
#result article:last-child { border-radius: 0 0 4px 4px; }
#result article:hover {
background-color: white;
color: dodgerblue;
}
#result .searching {
width: 192px; height: 30px; line-height: 30px;
padding: 0 12px;
background-color: dodgerblue; color: white;
border-radius: 4px;
}
Step 1. 검색된 결과값들 보여주기
타이핑된 키워드 검색
const { fromEvent, from } = rxjs
const { ajax } = rxjs.ajax
const { mergeMap, switchMap, pluck, retry, map, scan, filter, debounceTime, distinctUntilChanged } = rxjs.operators
const url = 'http://127.0.0.1:3000/people/quarter-error'
const keyword = document.querySelector('#keyword')
const result = document.querySelector('#result')
fromEvent(keyword, 'keyup').pipe(
pluck('target', 'value'),
mergeMap(keyword =>
ajax(`${url}?name=${keyword}`).pipe(retry(3))
),
pluck('response')
).subscribe(console.log)
결과 하단에 출력
function showResults (results) {
from(results).pipe(
map(person => `${person.first_name} ${person.last_name}`),
map(name => `<article>${name}</article>`),
scan((acc, article) => acc += article, '')
).subscribe(people => result.innerHTML = people)
}
다음 ajax가 호출되면 이전 과정을 멈추도록
fromEvent(keyword, 'keyup').pipe(
pluck('target', 'value'),
// meregeMap 대신 switchMap 사용
switchMap(keyword =>
ajax(`${url}?name=${keyword}`).pipe(retry(3))
),
pluck('response')
).subscribe(showResults)
불필요한 Ajax 요청 생략
fromEvent(keyword, 'keyup').pipe(
pluck('target', 'value'),
filter(typed => typed.length > 1), // 1글자 이상일 때만
debounceTime(500), // 0.5초 공백 후 발행
distinctUntilChanged(), // 연속된 같은 문자열 생략
switchMap(keyword =>
ajax(`${url}?name=${keyword}`).pipe(retry(3))
),
pluck('response')
).subscribe(showResults)
백스페이스를 누를 때 변화한 값으로 검색되지 않도록
fromEvent(keyword, 'keyup').pipe(
filter(event => event.code != 'Backspace'), // 백스페이스 생략
pluck('target', 'value'),
filter(typed => typed.length > 1),
debounceTime(500),
distinctUntilChanged(),
switchMap(typed =>
ajax(`${url}?name=${typed}`).pipe(retry(3))
),
pluck('response')
).subscribe(showResults)
Step2. 상태표시 추가
- 스트림을 입력받는 부분과 그 이후의 Ajax 결과로 분리
- 두 스트림의 결과를
merge
하여 한 subscriber에 적용
const { fromEvent, from, merge } = rxjs
const { ajax } = rxjs.ajax
const { mergeMap, switchMap, pluck, retry, map, filter, debounceTime, distinctUntilChanged, mapTo, scan } = rxjs.operators
const url = 'http://127.0.0.1:3000/people/quarter-error'
const keyword = document.querySelector('#keyword')
const result = document.querySelector('#result')
const searchInit$ = fromEvent(keyword, 'keyup').pipe(
filter(event => event.code != 'Backspace'), // 백스페이스 생략
pluck('target', 'value'),
filter(typed => typed.length > 1),
debounceTime(500),
distinctUntilChanged()
)
const searching$ = searchInit$.pipe(
mapTo('<div class="searching">Searching...</div>')
)
const searchResult$ = searchInit$.pipe(
switchMap(keyword =>
ajax(`${url}?name=${keyword}`).pipe(retry(3))
),
pluck('response'),
mergeMap(results => from(results).pipe(
map(person => `${person.first_name} ${person.last_name}`),
map(name => `<article>${name}</article>`),
scan((acc, article) => acc += article, '')
))
)
merge(
searching$,
searchResult$
).subscribe(text => result.innerHTML = text)
🤔얄코에게 질문하기질문은 반.드.시 이리로 보내주세요! ( 강의사이트 질문기능 ✖ )
🛑질문 전 필독!!
- 구글링을 먼저 해 주세요. 들어오는 질문의 절반 이상은 구글에 검색해 보면 1분 이내로 답을 찾을 수 있는 내용들입니다.
- 오류 메시지가 있을 경우 이를 구글에 복붙해서 검색해보면 대부분 짧은 시간 내 해결방법을 찾을 수 있습니다.
- 강의 페이지에 추가사항 등 놓친 부분이 없는지 확인해주세요. 자주 들어오는 질문은 페이지에 추가사항으로 업데이트됩니다.
- "유료파트의 강의페이지는 어디 있나요?" - 각 영상의 시작부분 검은 화면마다 해당 챕터의 강의페이지 링크가 있습니다.
- 질문을 보내주실 때는 문제가 어떻게 발생했고 어떤 상황인지 등을 구체적으로 적어주세요. 스크린샷을 첨부해주시면 더욱 좋습니다.