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)

🤔얄코에게 질문하기질문은 반.드.시 이리로 보내주세요! ( 강의사이트 질문기능 ✖ )

강의에서 이해가 안 되거나 실습상 문제가 있는 부분,
설명이 잘못되었거나 미흡한 부분을 메일로 알려주세요!

답변드린 뒤 필요할 경우 본 페이지에
관련 내용을 추가/수정하도록 하겠습니다.

이메일 주소
yalco@yalco.kr
메일 제목 (반드시 아래 제목을 붙여넣어주세요!)
[질문] RxJS 3-1

🛑질문 전 필독!!

  • 구글링을 먼저 해 주세요. 들어오는 질문의 절반 이상은 구글에 검색해 보면 1분 이내로 답을 찾을 수 있는 내용들입니다.
  • 오류 메시지가 있을 경우 이를 구글에 복붙해서 검색해보면 대부분 짧은 시간 내 해결방법을 찾을 수 있습니다.
  • 강의 페이지에 추가사항 등 놓친 부분이 없는지 확인해주세요. 자주 들어오는 질문은 페이지에 추가사항으로 업데이트됩니다.
  • "유료파트의 강의페이지는 어디 있나요?" - 각 영상의 시작부분 검은 화면마다 해당 챕터의 강의페이지 링크가 있습니다.
  • 질문을 보내주실 때는 문제가 어떻게 발생했고 어떤 상황인지 등을 구체적으로 적어주세요. 스크린샷을 첨부해주시면 더욱 좋습니다.
🌏 Why not change the world?