Callbacks
var isLoaded = false;
$.ajax({
url:'http://blah.api.com',
success:function(resp){
isLoaded = true;
}
});
var isLoaded = false;
var isBlah1Loaded = false;
var isBlah2Loaded = false;
$.ajax({
url:'blah1',
success:function(resp){
isBlah1Loaded = true;
if(isBlah2Loaded){
isLoaded = true;
}
}
});
$.ajax({
url:'blah2',
success:function(resp){
isBlah2Loaded = true;
if(isBlah1Loaded){
isLoaded = true;
}
}
});
But there are promises!
Promise cons
Lets look at RxJS
A concept of Reactive extensions.
Java, c#, Python, Ruby, Scala
and Javascript!
Reactive Observables
Collection of values over time is modeled as an Observable in Rx.js
Reactive Observables
Can model
Stream => Infinite length/lazily evaluated.
observable
observer
do stuff
onCompleted
onError
onNext
observer
side effects
side effects
var searchWikipedia = function(query){
var promise = $.ajax({
url:"https://en.wikipedia.org/w/api.php",
dataType:'jsonp',
data:{
action:"query",
format:"json",
list:"search",
srsearch:query
}
}).promise();
return Rx.Observable.fromPromise(promise);
}
Rx.Observable.from(['Led Zeppelin', 'The Kinks', 'CCR']);
Rx.Observable.create(function(observer){
try{
if(condition){
observer.onNext(42);
} else {
observer.onCompleted();
}
}catch(e){
observer.onError(e);
}
return disposeFn;
});
Subscriber(observer)
var source = Rx.Observable.from(['Led Zeppelin', 'The Kinks', 'CCR']);
source.subscribe(function(value){
console.log(value)
}, function(error){
console.log('error')
}, function(){
console.log('done');
});
//OUTPUT
//Led Zeppelin
//The Kinks
//CCR
//done
map
filter
flatMap
concatMap
sample
skip
takeUntil
take
delay
distinctUntilChanged
find
join
max
mergeAll
reduce
pluck
retry
throttle
debounce
transduce
zip
and many more...
Combinators!
var queries = ['Led Zeppelin', 'Pink Floyd', 'The Kinks', 'Foo Fighters', 'Doobie Brothers'];
var queryObs = Rx.Observable.from(queries);
var source = queryObs
.flatMap(searchWikipedia)
.map(function(searchRes){ return searchRes.query.search[2].title; })
.zip(queries, function(s1, s2){
return s2 + ' - [Wiki response]' + s1;
});
var sub = source.subscribe(function(val){
console.log(val);
}, function(err){
console.log(err);
}, function(done){
console.log('done');
});
Xhr with Rx Observables
Observables
Reactive
Combinators
Functional
Autocomplete widget
var $input = $('#textInput');
// Get all distinct key up events from the input and only fire if long enough and distinct
var source = Rx.Observable.fromEvent($input, 'keyup')
.map(function (e) {
return e.target.value; // Project the text from the input
})
.filter(function (text) {
return text.length > 2; // Only if the text is longer than 2 characters
})
.debounce(750 /* Pause for 750ms */ )
.distinctUntilChanged() // Only if the value has changed
.flatMapLatest(searchWikipedia)
source.subscribe(function (data) {
updateResults(data);
},
function (error) {
showError();
});
Drag and Drop with Rxjs
var dragTarget = $('#dragTarget'),
mouseup = dragTarget.onAsObservable('mouseup'),
mousemove = dragTarget.onAsObservable('mousemove'),
mousedown = dragTarget.onAsObservable('mousedown')
.map(function (event) {
event.preventDefault();
return {
left: event.clientX - dragTarget.offset().left,
top: event.clientY - dragTarget.offset().top
};
}),
mousedrag = mousedown.flatMapLatest(function(imageOffset) {
return mousemove.select(function (pos) {
return {
left: pos.clientX - imageOffset.left,
top: pos.clientY - imageOffset.top
};
}).takeUntil(mouseup);
});
mousedrag.subscribe (function (pos) {
$('#dragTarget').css({top: pos.top, left: pos.left});
});
Vanilla Js/Jquery/Node
For your MV* Framework
Advanced stuff
Takeaways
Alternatives
FRP in production
Resources