var produceEvent = document.getElementById('produce-event'); var pending = document.getElementById('pending'); var inProgress = document.getElementById('in-progress'); var done = document.getElementById('done'); var inProgressCount = 0; var events$ = Rx.Observable.fromEvent(produceEvent, 'click') .do(({timeStamp}) => updatePanelAppend(pending, Math.floor(timeStamp*1000))); var inProgress$ = events$; var done$ = inProgress$ .flatMap(({timeStamp}) => Rx.Observable.defer(() => { updatePanelAppend(inProgress, Math.floor(timeStamp*1000)); removeFromPanel(pending, Math.floor(timeStamp*1000)); return expensiveComputation(getRandomInt(1, 5) * 1000, Math.floor(timeStamp*1000)); }), 1); done$.subscribe((timeStamp) => { updatePanelAppend(done, timeStamp); removeFromPanel(inProgress, timeStamp); }); function updatePanelAppend(panelEl, newContent) { var newDiv = document.createElement('div'); newDiv.id = '_' + newContent; newDiv.textContent = newContent + ','; panelEl.appendChild(newDiv); } function removeFromPanel(panelEl, timeStamp) { var el = panelEl.querySelector('#_' + timeStamp); panelEl.removeChild(el); } /** * Simulate an expensive function that returns a promise **/ function expensiveComputation(time, result) { console.log('expensiveComputation for:' + result); if (!time) { time = 1000; } return Q.delay(time).then(()=> result); } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }