JSFiddle - React, Tailwind, and code Playground
by junseok choi
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
<div class="container">
<div class="header">
<h3>Who to follow</h3><a href="#" class="refresh">Refresh</a>
</div>
<ul class="suggestions">
<li class="suggestion1">
<img />
<a href="#" target="_blank" class="username">this will not be displayed</a>
<a href="#" class="close close1">x</a>
</li>
<li class="suggestion2">
<img />
<a href="#" target="_blank" class="username">neither this</a>
<a href="#" class="close close2">x</a>
</li>
<li class="suggestion3">
<img />
<a href="#" target="_blank" class="username">nor this</a>
<a href="#" class="close close3">x</a>
</li>
</ul>
</div>
CSS
body {
font-family: sans-serif;
padding: 10px;
}
h3 {
font-weight: bold;
display: inline-block;
padding: 0;
margin: 0;
}
.refresh {
font-size: 80%;
margin-left: 10px;
}
.header {
background: #ECECEC;
padding: 5px;
}
.suggestions {
border: 2px solid #ECECEC;
}
li {
padding: 5px;
}
li img {
width: 40px;
height: 40px;
border-radius: 20px;
}
li .username, li .close {
display: inline-block;
position: relative;
bottom: 15px;
left: 5px;
}
JavaScript
// 1. refresh element에 click 이벤트 스트림 생성
var refreshStream = Rx.Observable.fromEvent(document.querySelector(".refresh"), "click");
// 2-1. 1번에서 정의한 스트림에 map을 설정합니다. 이벤트의 스트림마다 해당 이벤트를 실행하겠다고 설정해주는 것 입니다.
// 2-2. just는 초기 데이터가 없기에 trigger로 실행해줍니다.
// 2-3. 두 이벤트 스트림을 merge해서 requestStream을 만듭니다.
// 2-4. 두 이벤트 스트림이 배열로 들어갑니다.
var requestStream = Rx.Observable.just(getUsers()).merge(refreshStream.map(getUsers));
// 3-1. flatMap은 이벤트 스트림을 하나로 합쳐줍니다.
// 3-2. 처음부터 refresh 이벤트가 발생했을리는 없으니 초기에 들어가는 url은 just로 실행해준 값이 될겁니다.
// 3-3. shareReplay는 parameter로 넘겨준 숫자만큼의 item들을 최초 subscribe에서만 처리하여 가지고 있다가, 이후의 subscribe에서는 최초에 가지고 있던 item들을 replay하기 위한 operator입니다.
// 3-4. https://codepen.io/HipsterZipster/pen/aZJeBm
// 3-5. 위 url을 보고 오신다면 responseStream 이벤트가 발생한다면, 가장 마지막 값이 남아있다는 것을 아시게 될겁니다.
var responseStream = requestStream.flatMap( url => {
console.log("request url : " + url);
return Rx.Observable.fromPromise(jQuery.getJSON(url));
}).shareReplay(1);
// 4-1. responseStream 이벤트 발생시 getRandomUser를 실행시킵니다.
// 4-2. 초기값은 없습니다. (초기부터 close 이벤트가 실행되지 않음) / 사실 startWith가 없어도 문제가 생기지 않음
// 4-3. withLastestFrom은 두 개의 이벤트 스트림을 합성하지만, 한쪽 이벤트 스트림의 이벤트가 발생할 때에만 합성을 해줍니다.
// 4-4. 이 메서드를 사용하면, 스트림을 합성할 때 이벤트를 추가할 수 있습니다.
function createLineStream(closeStream) {
// null, user
return responseStream.map(getRandomUser)
.startWith(null)
.merge(closeStream.withLatestFrom(responseStream, (evt, users) => {
return getRandomUser(users);
}));
}
var close1Stream = Rx.Observable.fromEvent(document.querySelector(".close1"), "click");
var close2Stream = Rx.Observable.fromEvent(document.querySelector(".close2"), "click");
var close3Stream = Rx.Observable.fromEvent(document.querySelector(".close3"), "click");
var line1Stream = createLineStream(close1Stream);
var line2Stream = createLineStream(close2Stream);
var line3Stream = createLineStream(close3Stream);
// Run
line1Stream.subscribe(user => {
renderUser(".suggestion1", user);
});
line2Stream.subscribe(user => {
...