Created
September 27, 2013 06:55
-
-
Save MikeBild/6725003 to your computer and use it in GitHub Desktop.
reactive applications - some examples
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
<!DOCTYPE HTML> | |
<html> | |
<head> | |
<title>Reactive Applications</title> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.1.11/rx.min.js"></script> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.1.11/rx.aggregates.min.js"></script> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.1.18/rx.time.min.js"></script> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.1.11/rx.binding.min.js"></script> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/2.0.7/rx.dom.min.js"></script> | |
</head> | |
<body> | |
<ul id="sections"> | |
<li>EventDriven</li> | |
<li>Scalable</li> | |
<li>Resilient</li> | |
<li>Interactive</li> | |
</ul> | |
<section id="EventDriven" style="display: none"> | |
<span>Event-Driven</span> | |
<div> | |
<div>Product Price: 8.0</div> | |
<div>Number: <span id="displayNumber">0</span></div> | |
<div>Amount: <span id="displayAmount">0.0</span></dov> | |
<button id="more">more</button> | |
<button id="less">less</button> | |
</div> | |
</section> | |
<section id="Scalable" style="display: none"> | |
<span>Scalable</span> | |
<div> | |
<ul id="displayScalable"></ul> | |
</div> | |
</section> | |
<section id="Resilient" style="display: none"> | |
<span>Resilient</span> | |
<div> | |
<ul id="displayResilient"></ul> | |
</div> | |
</section> | |
<section id="Interactive" style="display: none"> | |
<span>Interactive</span> | |
<div> | |
<input type="text" id="textInput"> | |
<ul id="results"></ul> | |
</div> | |
</section> | |
<script> | |
var Basics = function() { | |
var _eventdriven = function(){ | |
var Dal = function(){ | |
var _self = this; | |
var _events = []; | |
var _load = function(){ | |
return Rx.Observable.fromArray(_events); | |
}; | |
var _save = function(event){ | |
_events.push(event); | |
}; | |
return { | |
load : _load, | |
save: _save | |
} | |
}; | |
var Logic = function(){ | |
var _calculatePrice = function(stream, price){ | |
return stream | |
.map(function(x){ | |
return x.Type === "added" ? 1 : -1; | |
}) | |
.aggregate(function(acc, x) { | |
return acc + x; | |
}) | |
.map(function(next){ | |
return new Cart(price, next, next * price); | |
}); | |
}; | |
return { | |
calculatePrice: _calculatePrice | |
}; | |
}; | |
var Cart = function(price, count, amount){ | |
return { | |
Count: count || 0, | |
Amount: amount || 0.0 | |
} | |
}; | |
var Action = function(type){ | |
return { | |
Type: type || "", | |
} | |
}; | |
var View = function() { | |
var _displayAmount = function(value){ | |
document.getElementById('displayAmount').innerText = value; | |
}; | |
var _displayNumber = function(value){ | |
document.getElementById('displayNumber').innerText = value; | |
}; | |
var _onMore = function(){ | |
return Rx.DOM.fromEvent(document.getElementById('more'), 'click'); | |
}; | |
var _onLess = function(){ | |
return Rx.DOM.fromEvent(document.getElementById('less'), 'click'); | |
} | |
return { | |
displayNumber: _displayNumber, | |
displayAmount: _displayAmount, | |
onMore: _onMore, | |
onLess: _onLess | |
}; | |
}; | |
var view = new View(); | |
var logic = new Logic(); | |
var dal = new Dal(); | |
var moreStream = view.onMore() | |
.doAction(function(next){ | |
dal.save(new Action("added")); | |
}); | |
var lessStream = view.onLess() | |
.doAction(function(next){ | |
dal.save(new Action("removed")); | |
}); | |
return moreStream | |
.merge(lessStream) | |
.flatMap(function(next){ | |
return logic.calculatePrice(dal.load(), 8.0); | |
}) | |
.doAction(function(next){ | |
view.displayNumber(next.Count); | |
view.displayAmount(next.Amount); | |
}) | |
.subscribe(); | |
}; | |
var _scalable = function(){ | |
var displayScalable = function(value){ | |
var ul = document.getElementById("displayScalable"); | |
var newLi = document.createElement("li"); | |
ul.appendChild(newLi); | |
newLi.innerHTML = value; | |
} | |
return Rx.Observable.interval(1000) | |
.observeOn(Rx.Scheduler.requestAnimationFrame) | |
.doAction(function(){ | |
displayScalable("map requestAnimationFrame"); | |
}) | |
.observeOn(Rx.Scheduler.mutationObserver) | |
.doAction(function(){ | |
displayScalable("reduce mutationObserver"); | |
}) | |
.observeOn(Rx.Scheduler.timeout) | |
.doAction(function(){ | |
displayScalable("map with timeout"); | |
}) | |
.observeOn(Rx.Scheduler.immediate) | |
.doAction(function(){ | |
displayScalable("reduce immediate"); | |
}) | |
.subscribe(); | |
}; | |
var _resilient = function(){ | |
var displayResilient = function(value){ | |
var ul = document.getElementById("displayResilient"); | |
var newLi = document.createElement("li"); | |
ul.appendChild(newLi); | |
newLi.innerHTML = value; | |
} | |
function DisposableResource(value) { | |
var self = this, | |
value = null, | |
disposed = false; | |
self.getValue = function() { | |
if (this.disposed) { | |
throw new Error('Object is disposed'); | |
} | |
return this.value; | |
}; | |
self.dispose = function() { | |
if (!this.disposed) { | |
this.disposed = true; | |
this.value = null; | |
} | |
displayResilient('disposed!'); | |
} | |
} | |
var subject = new Rx.Subject(); | |
var binding = Rx.Observable.using(function() { | |
return new DisposableResource(42) | |
}, function(resource){ | |
return subject.asObservable(); | |
}); | |
var stream = binding | |
// .catchException(Rx.Observable.returnValue(100)) | |
// .onErrorResumeNext(Rx.Observable.returnValue(200)) | |
.doAction(function(next){ | |
displayResilient(next); | |
}, | |
function(error){ | |
displayResilient(error); | |
}, | |
function(){ | |
displayResilient("done!"); | |
}) | |
// .retry(3) | |
.finallyAction(function () { | |
displayResilient('finally!'); | |
}); | |
var subscription = stream.subscribe(); | |
subject.onNext("1"); | |
subject.onNext("2"); | |
// subject.onError("error"); | |
// subject.onCompleted(); | |
subject.onNext("3"); | |
subscription.dispose(); | |
return subscription; | |
}; | |
var _interactive = function(){ | |
function searchWikipedia (term) { | |
var url = 'http://en.wikipedia.org/w/api.php?action=opensearch&format=json&search=' + term + '&callback=JSONPCallback'; | |
return Rx.DOM.Request.jsonpRequest(url); | |
} | |
function resetDisplay() { | |
var ul = document.getElementById('results'); | |
while (ul.firstChild) { | |
ul.removeChild(ul.firstChild); | |
} | |
} | |
function displayResults(data){ | |
var ul = document.getElementById('results'), | |
results = data[1]; | |
resetDisplay(); | |
for (var i = 0, len = results.length; i < len; i++) { | |
var li = document.createElement('li'); | |
li.innerHTML = results[i]; | |
ul.appendChild(li); | |
} | |
} | |
function displayError(error){ | |
var ul = document.getElementById('results'); | |
resetDisplay(); | |
var li = document.createElement('li'); | |
li.innerHTML = 'Error: ' + error.message; | |
ul.appendChild(li); | |
} | |
return Rx.DOM.fromEvent(document.getElementById('textInput'), 'keyup') | |
.map(function(next) { | |
return next.target.value; | |
}) | |
.filter(function(next) { | |
return next.length > 2; | |
}) | |
.throttle(250) | |
.distinctUntilChanged() | |
.map(function (next) { | |
return searchWikipedia(next); | |
}) | |
.switchLatest() | |
.filter(function (next) { | |
return next.length === 2; | |
}) | |
.doAction(displayResults, displayError) | |
.subscribe(); | |
}; | |
return { | |
EventDriven : _eventdriven, | |
Scalable: _scalable, | |
Resilient: _resilient, | |
Interactive: _interactive, | |
}; | |
}; | |
var activeSubscription, | |
samples = new Basics(); | |
input = Rx.DOM.fromEvent(document.getElementsByTagName('li'), 'click'); | |
input | |
.doAction(function(next){ | |
if(activeSubscription) activeSubscription.dispose(); | |
}) | |
.doAction(function(next){ | |
var sections = Array.prototype.slice.call(document.getElementsByTagName("section")); | |
sections.forEach(function(section){ | |
section.style.display = "none"; | |
}); | |
}) | |
.map(function(next){ | |
return next.target.innerText; | |
}) | |
.filter(function(next){ | |
return next !== ""; | |
}) | |
.doAction(function(next){ | |
var section = document.getElementById(next); | |
if(section !== null) section.style.display = "block"; | |
}) | |
.doAction(function(next){ | |
activeSubscription = samples[next](); | |
}) | |
.subscribe(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment