async javascript at netflix jafar husain @jhusain
TRANSCRIPT
![Page 1: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/1.jpg)
Async JavaScript at Netflix
Jafar Husain@jhusain
![Page 2: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/2.jpg)
Who is Jafar?Cross-Team Technical Lead for Netflix UIs
Architect of Netflix UI Data PlatformMember of JavaScript standards committee (TC39)
16 years in the industry, formerly worked at Microsoft and GE
![Page 3: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/3.jpg)
This is the story of how Netflix solved
BIG async problems
by thinking differently about
Events.
![Page 4: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/4.jpg)
2014321
![Page 5: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/5.jpg)
Async Programming was very
HARD
![Page 6: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/6.jpg)
The Netflix App was plagued byRace ConditionsMemory LeaksComplex State MachinesUncaught Async Errors
![Page 7: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/7.jpg)
Playing a Movie Asynchronouslyfunction play(movieId, cancelButton, callback) { var movieTicket, playError, tryFinish = function() { if (playError) { callback(null, playError); } else if (movieTicket && player.initialized) { callback(null, ticket); } }; cancelButton.addEventListener(“click”, function() { playError = “cancelled”; } if (!player.initialized) { player.init(function(error) { playError = error; tryFinish(); } } authorizeMovie(function(error, ticket) { playError = error; movieTicket = ticket; tryFinish(); });});
function play(movieId, cancelButton, callback) { var movieTicket, playError, tryFinish = function() { if (playError) { callback(null, playError); } else if (movieTicket && player.initialized) { callback(null, ticket); } }; cancelButton.addEventListener(“click”, function() { playError = “cancelled”; } if (!player.initialized) { player.init(function(error) { playError = error; tryFinish(); }); } authorizeMovie(function(error, ticket) { playError = error; movieTicket = ticket; tryFinish(); });});
function play(movieId, cancelButton, callback) { var movieTicket, playError, tryFinish = function() { if (playError) { callback(null, playError); } else if (movieTicket && player.initialized) { callback(null, ticket); } }; cancelButton.addEventListener(“click”, function() { playError = “cancelled”; } if (!player.initialized) { player.init(function(error) { playError = error; tryFinish(); }); } authorizeMovie(function(error, ticket) { playError = error; movieTicket = ticket; tryFinish(); });});
function play(movieId, cancelButton, callback) { var movieTicket, playError, tryFinish = function() { if (playError) { callback(null, playError); } else if (movieTicket && player.initialized) { callback(null, ticket); } }; cancelButton.addEventListener(“click”, function() { playError = “cancelled”; } if (!player.initialized) { player.init(function(error) { playError = error; tryFinish(); } } authorizeMovie(function(error, ticket) { playError = error; movieTicket = ticket; tryFinish(); });});
![Page 8: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/8.jpg)
the majority of Netflix’s async code
is written with just a few flexible functions.
Today
![Page 9: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/9.jpg)
But first a brief
JavaScript 6 tutorial…
![Page 10: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/10.jpg)
Functions
x + 1function(x) { return x + 1; }x =>function(x, y) { return x + y; }(x,
y)x + y =>
JS65
![Page 11: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/11.jpg)
Fin.
![Page 12: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/12.jpg)
ForEach
> [1, 2, 3].forEach(x => console.log(x))> 1> 2> 3>
![Page 13: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/13.jpg)
Map
![Page 14: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/14.jpg)
Map
> [1, 2, 3].map(x => x + 1)> [2, 3, 4]>
![Page 15: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/15.jpg)
Filter
![Page 16: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/16.jpg)
Filter
> [1, 2, 3].filter(x => x > 1)> [2, 3]>
![Page 17: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/17.jpg)
concatAll
![Page 18: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/18.jpg)
concatAll
> [ [1], [2, 3], [], [4] ].concatAll()> [1, 2, 3, 4]>
![Page 19: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/19.jpg)
Map/Filter/ConcatAll> [1, 2, 3].map(x => x + 1)> [2, 3, 4]
> [1, 2, 3].filter(x => x > 1)> [2, 3]
> [ [1], [2, 3], [], [4] ].concatAll()> [1, 2, 3, 4]>
![Page 20: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/20.jpg)
![Page 21: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/21.jpg)
Let’s use map, filter, and concatAll to get a list of your favorite Netflix titles.
![Page 22: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/22.jpg)
Top-rated Movies Collection
var getTopRatedFilms = user => user.videoLists. map(videoList => videoList.videos. filter(video => video.rating === 5.0)). concatAll();
getTopRatedFilms(user). forEach(film => console.log(film));
![Page 23: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/23.jpg)
What if I told you……that you could create a drag event…
…with nearly the same code?
![Page 24: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/24.jpg)
Top-rated Movies Collection
var getTopRatedFilms = user => user.videoLists. map(videoList => videoList.videos. filter(video => video.rating === 5.0)). concatAll();
getTopRatedFilms(user). forEach(film => console.log(film));
![Page 25: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/25.jpg)
Mouse Drags Collection
var getElementDrags = elmt => elmt.mouseDowns. map(mouseDown => document.mouseMoves. filter takeUntil(document.mouseUps)). concatAll();
getElementDrags(image). forEach(pos => image.position = pos);
![Page 26: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/26.jpg)
“What’s the difference between an Array…
[{x: 23, y: 44}, {x:27, y:55}, {x:27, y:55}]
![Page 27: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/27.jpg)
… and an Event?
{x: 23, y: 44}...{x:27, y:55}.... {x:27, y:55}......
![Page 28: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/28.jpg)
Events and Arrays are both
collections.
![Page 29: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/29.jpg)
So why don’t we program them the same way?
![Page 30: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/30.jpg)
![Page 31: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/31.jpg)
![Page 32: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/32.jpg)
Iterator
Observer
?
![Page 33: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/33.jpg)
Iterator> var iterator = [1,2,3].iterator();
> { value: 1, done: false }>
> console.log(iterator.next());
> console.log(iterator.next());
> { value: 2, done: false }>> console.log(iterator.next());
> { value: 3, done: false }>> console.log(iterator.next());
> { done: true }>
![Page 34: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/34.jpg)
Map, Filter, and ConcatAll can be implemented using an
Iterator.
![Page 35: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/35.jpg)
Observer Pattern> document.addEventListener( “mousemove”, function next(e) { console.log(e); });
> { clientX: 425, clientY: 543 }> { clientX: 450, clientY: 558 }> { clientX: 455, clientY: 562 }> { clientX: 460, clientY: 743 }> { clientX: 476, clientY: 760 }> { clientX: 476, clientY: 760 }> { clientX: 476, clientY: 760 }> { clientX: 476, clientY: 760 }
![Page 36: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/36.jpg)
Iterator Observerprogressively send information to consumer
![Page 37: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/37.jpg)
The Iterator and Observer Pattern are Symmetrical.
![Page 38: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/38.jpg)
![Page 39: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/39.jpg)
The authors of “Design Patterns”
missed
this symmetry.
![Page 40: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/40.jpg)
As a result, they gave
Iterator and Observer different semantics.
![Page 41: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/41.jpg)
So Many Push APIs
DOM EventsWebsockets
Server-sent EventsNode StreamsService WorkersjQuery EventsXMLHttpRequestsetInterval
![Page 42: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/42.jpg)
Observable === Collection + Time
Introducing Observable
![Page 43: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/43.jpg)
Observables can model…EventsAnimationsAsync Server Requests
![Page 44: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/44.jpg)
Reactive ExtensionsEvents as StreamsOpen Source (Apache2)Ported to many languages
C .NET JavaScript Java (Netflix)Objective-C
![Page 45: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/45.jpg)
http://reactivex.io
![Page 46: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/46.jpg)
Events to Observables
var mouseMoves = Observable. fromEvent(element, “mousemove”);
![Page 47: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/47.jpg)
Adapt Push APIs to Observable
DOM EventsWebsockets
Server-sent EventsNode StreamsService WorkersjQuery EventsXMLHttpRequestsetInterval
Observable
![Page 48: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/48.jpg)
Event Subscription
// “subscribe”var handler = (e) => console.log(e);document.addEventListener(“mousemoves”, handler);
// “unsubscribe”document.removeEventListener(“mousemoves”, handler);
![Page 49: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/49.jpg)
Observable.forEach
// “subscribe”var subscription = mouseMoves.forEach(console.log);
// “unsubscribe”subscription.dispose();
![Page 50: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/50.jpg)
Expanded Observable.forEach// “subscribe”var subscription = mouseMoves.forEach( // next data event => console.log(event), // error error => console.error(error), // completed () => console.log(“done”));
// “unsubscribe”subscription.dispose();
optional
![Page 51: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/51.jpg)
Expanded Observable.forEach// “subscribe”var subscription = mouseMoves.forEach({ onNext: event => console.log(event), // error onError: error => console.error(error), // completed onCompleted: () => console.log(“done”) });
// “unsubscribe”subscription.dispose();
Observer
![Page 52: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/52.jpg)
Converting Events to Observables
Observable.fromEvent = function(dom, eventName) { // returning Observable object return { forEach: function(observer) { var handler = (e) => observer.onNext(e); dom.addEventListener(eventName, handler);
// returning Subscription object return { dispose: function() { dom.removeEventListener(eventName, handler); } }; } };}
![Page 53: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/53.jpg)
Observable Literal
JS6
time
{1……2…………3}
![Page 54: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/54.jpg)
ForEach
> {1……2…………3}.forEach(console.log)
> 1>> 2>> 3>
time
> {1……2…………3}
![Page 55: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/55.jpg)
Map
> {1……2…………3}.map(x => x + 1)
> 2>> 3>> 4>
time
![Page 56: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/56.jpg)
> 2> 3>
Filter
> {1……2…………3}.filter(x => x + 1)
> > 2>
time
![Page 57: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/57.jpg)
concatAll
[ [1] [2, 3], [], [4]].concatAll()
[1, 2, 3, 4]
![Page 58: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/58.jpg)
concatAll
{…{1}………{2………………3}, ……………{}………………{4}}.concatAll()
{…1…2………………3…4}
time
![Page 59: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/59.jpg)
TakeUntil
{…1…2…………3}.takeUntil({……………4})
{…1…2…}
timeSource collection
Stop collection
![Page 60: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/60.jpg)
Mouse Drags Collection
var getElementDrags = elmt => elmt.mouseDowns. map(mouseDown => document.mouseMoves. takeUntil(document.mouseUps)). concatAll();
getElementDrags(image). forEach(pos => image.position = pos);
![Page 61: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/61.jpg)
mergeAll
{…{1}………{2………………3}, ……………{}………………{4}}.mergeAll()
{…1…2……4………3}
time
![Page 62: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/62.jpg)
switchLatest
{…{1}………{2………………3}, ……………{}………………{4}}.switchLatest()
{…1…2……4}
time
subscription.dispose()
![Page 63: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/63.jpg)
Don’t unsubscribe from Events.
Complete them when another event fires.
![Page 64: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/64.jpg)
Mouse Drags Collection
var getElementDrags = elmt => elmt.mouseDowns. map(mouseDown => document.mouseMoves. takeUntil(document.mouseUps)). concatAll();
getElementDrags(image). forEach(pos => image.position = pos);
![Page 65: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/65.jpg)
Netflix Search
![Page 66: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/66.jpg)
Netflix Searchvar searchResultSets = keyPresses. throttle(250). map(key => getJSON(“/searchResults?q=” + input.value). retry(3). takeUntil(keyPresses)). concatAll();
searchResultSets.forEach( resultSet => updateSearchResults(resultSet), error => showMessage(“the server appears to be down.”));
![Page 67: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/67.jpg)
Netflix Searchvar searchResultSets = keyPresses. throttle(250). map(key => getJSON(“/searchResults?q=” + input.value). retry(3). takeUntil(keyPresses)). concatAll switchLatest();
searchResultSets.forEach( resultSet => updateSearchResults(resultSet), error => showMessage(“the server appears to be down.”));
![Page 68: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/68.jpg)
Netflix Search
var searchResultSets = keyPresses. throttle(250). map(key => getJSON(“/searchResults?q=” + input.value). retry(3)). switchLatest();
searchResultSets.forEach( resultSet => updateSearchResults(resultSet), error => showMessage(“the server appears to be down.”));
![Page 69: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/69.jpg)
Netflix Player
![Page 70: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/70.jpg)
Player Callback Hellfunction play(movieId, cancelButton, callback) { var movieTicket, playError, tryFinish = function() { if (playError) { callback(null, playError); } else if (movieTicket && player.initialized) { callback(null, ticket); } }; cancelButton.addEventListener(“click”, function() { playError = “cancel”; }); if (!player.initialized) { player.init(function(error) { playError = error; tryFinish(); } } authorizeMovie(movieId, function(error, ticket) { playError = error; movieTicket = ticket; tryFinish(); });});
![Page 71: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/71.jpg)
Player with Observablevar authorizations = player. init(). map(() => playAttempts. map(movieId => player.authorize(movieId).
catch(e => Observable.empty). takeUntil(cancels)). concatAll())). concatAll(); authorizations.forEach( license => player.play(license), error => showDialog(“Sorry, can’t play right now.”));
![Page 72: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/72.jpg)
Netflix: Observable EverywhereApp StartupPlayerData AccessAnimationsView/Model binding
![Page 73: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/73.jpg)
Interactive Learning Exercises
http://jhusain.github.io/learnrx/
![Page 74: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/74.jpg)
Observable in JavaScript 7?async function* getStocks() { let reader = new AsyncFileReader(“stocks.txt”); try { while(!reader.eof) { let line = await reader.readLine(); await yield JSON.parse(line); } } finally { reader.close(); }}
async function writeStockInfos() { let writer = new AsyncFileWriter(“stocksAndPrices.txt”); try { for(let name on getStocks()) { let price = await getStockPrice(name); await writer.writeLine(JSON.stringify({name, price})); } } finally { writer.close(); }}
![Page 75: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/75.jpg)
Resources reactivetrader.azurewebsites.net https://github.com/Reactive-Extensions/RxJS RxJava http://jhusain.github.io/learnrx/ @jhusain
![Page 76: Async JavaScript at Netflix Jafar Husain @jhusain](https://reader034.vdocuments.us/reader034/viewer/2022051017/56649ccc5503460f9499683c/html5/thumbnails/76.jpg)
Questions