SlideShare uma empresa Scribd logo
1 de 79
Async JavaScript at Netflix
Jafar Husain
@jhusain
InfoQ.com: News & Community Site
• 750,000 unique visitors/month
• Published in 4 languages (English, Chinese, Japanese and Brazilian
Portuguese)
• Post content from our QCon conferences
• News 15-20 / week
• Articles 3-4 / week
• Presentations (videos) 12-15 / week
• Interviews 2-3 / week
• Books 1 / month
Watch the video with slide
synchronization on InfoQ.com!
http://www.infoq.com/presentations
/async-programming-netflix
Purpose of QCon
- to empower software development by facilitating the spread of
knowledge and innovation
Strategy
- practitioner-driven conference designed for YOU: influencers of
change and innovation in your teams
- speakers and topics driving the evolution and innovation
- connecting and catalyzing the influencers and innovators
Highlights
- attended by more than 12,000 delegates since 2007
- held in 9 cities worldwide
Presented at QCon San Francisco
www.qconsf.com
Who is Jafar?
Cross-Team Technical Lead for Netflix UIs
Architect of Netflix UI Data Platform
Member of JavaScript standards committee
(TC39)
16 years in the industry, formerly worked at
Microsoft and GE
This is the story of how Netflix solved
BIGasync problems
by thinking differently about
Events.
2014
321
Async Programming was very
HARD
The Netflix App was plagued by
Race Conditions
Memory Leaks
Complex State Machines
Uncaught Async Errors
Playing a Movie Asynchronously
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();
});
});
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();
});
});
the majority of Netflix’s async code
is written with just a few flexible
functions.
Today
But first a brief
JavaScript 6 tutorial…
Functions
x + 1function(x) { return x + 1; }x =>
function(x, y) { return x + y; }(x, y) x + y=>
JS
6
5
Fin.
ForEach
> [1, 2, 3].forEach(x => console.log(x))
> 1
> 2
> 3
>
Map
Map
> [1, 2, 3].map(x => x + 1)
> [2, 3, 4]
>
Filter
Filter
> [1, 2, 3].filter(x => x > 1)
> [2, 3]
>
concatAll
concatAll
> [ [1], [2, 3], [], [4] ].concatAll()
> [1, 2, 3, 4]
>
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]
>
Let’s use map, filter, and concatAll to
get a list of your favorite Netflix titles.
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));
What if I told you…
…that you could create a drag event…
…with nearly the same code?
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));
Mouse Drags Collection
var getElementDrags = elmt =>
elmt.mouseDowns.
map(mouseDown =>
document.mouseMoves.
filter takeUntil(document.mouseUps)).
concatAll();
getElementDrags(image).
forEach(pos => image.position = pos);
“What’s the difference between an Array…
[{x: 23, y: 44}, {x:27, y:55}, {x:27, y:55}]
… and an Event?
{x: 23, y: 44}...{x:27, y:55}.... {x:27, y:55}......
Events and Arrays are both
collections.
So why don’t we program
them the same way?
Iterator
Observer
?
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 }
>
Map, Filter, and ConcatAll can be
implemented using an Iterator.
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 }
Iterator Observerprogressively send information to consumer
The Iterator and Observer Pattern
are Symmetrical.
The authors of
“Design Patterns”
missedthis symmetry.
As a result, they gave
Iterator and Observer
different semantics.
So Many Push APIs
DOM Events
Websockets
Server-sent Events
Node Streams
Service Workers
jQuery Events
XMLHttpRequest
setInterval
Observable === Collection + Time
Introducing Observable
Observables can model…
Events
Animations
Async Server Requests
Reactive Extensions
Events as Streams
Open Source (Apache2)
Ported to many languages
C
.NET
JavaScript
Java (Netflix)
Objective-C
http://reactivex.io
Events to Observables
var mouseMoves =
Observable.
fromEvent(element, “mousemove”);
Adapt Push APIs to Observable
DOM Events
Websockets
Server-sent Events
Node Streams
Service Workers
jQuery Events
XMLHttpRequest
setInterval
Observable
Event Subscription
// “subscribe”
var handler = (e) => console.log(e);
document.addEventListener(“mousemoves”, handler);
// “unsubscribe”
document.removeEventListener(“mousemoves”, handler);
Observable.forEach
// “subscribe”
var subscription =
mouseMoves.forEach(console.log);
// “unsubscribe”
subscription.dispose();
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
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
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);
}
};
}
};
}
Observable Literal
JS6
time
{1……2…………3}
ForEach
> {1……2…………3}.forEach(console.log)
> 1
>> 2
>> 3
>
time
> {1……2…………3}
Map
> {1……2…………3}.map(x => x + 1)
> 2
>> 3
>> 4
>
time
> 2
> 3
>
Filter
> {1……2…………3}.filter(x => x + 1)
>> 2
>
time
concatAll
[
[1]
[2, 3],
[],
[4]
].concatAll()
[1, 2, 3, 4]
concatAll
{
…{1}
………{2………………3},
……………{}
………………{4}
}.concatAll()
{…1…2………………3…4}
time
TakeUntil
{…1…2…………3}.takeUntil(
{……………4})
{…1…2…}
time
Source collection
Stop collection
Mouse Drags Collection
var getElementDrags = elmt =>
elmt.mouseDowns.
map(mouseDown =>
document.mouseMoves.
takeUntil(document.mouseUps)).
concatAll();
getElementDrags(image).
forEach(pos => image.position = pos);
mergeAll
{
…{1}
………{2………………3},
……………{}
………………{4}
}.mergeAll()
{…1…2……4………3}
time
switchLatest
{
…{1}
………{2………………3},
……………{}
………………{4}
}.switchLatest()
{…1…2……4}
time
subscription.dispose()
Don’t unsubscribe from Events.
Complete them when another
event fires.
Mouse Drags Collection
var getElementDrags = elmt =>
elmt.mouseDowns.
map(mouseDown =>
document.mouseMoves.
takeUntil(document.mouseUps)).
concatAll();
getElementDrags(image).
forEach(pos => image.position = pos);
Netflix Search
Netflix Search
var 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.”));
Netflix Search
var 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.”));
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.”));
Netflix Player
Player Callback Hell
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 = “cancel”; });
if (!player.initialized) {
player.init(function(error) {
playError = error;
tryFinish();
}
}
authorizeMovie(movieId, function(error, ticket) {
playError = error;
movieTicket = ticket;
tryFinish();
});
});
Player with Observable
var 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.”));
Netflix: Observable Everywhere
App Startup
Player
Data Access
Animations
View/Model binding
Interactive Learning Exercises
http://jhusain.github.io/learnrx/
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();
}
}
Resources
 reactivetrader.azurewebsites.net
 https://github.com/Reactive-Extensions/RxJS
 RxJava
 http://jhusain.github.io/learnrx/
 @jhusain
Questions
Watch the video with slide synchronization
on InfoQ.com!
http://www.infoq.com/presentations/async-
programming-netflix

Mais conteúdo relacionado

Mais procurados

Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
Adieu
 

Mais procurados (20)

jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
Design patterns for microservice architecture
Design patterns for microservice architectureDesign patterns for microservice architecture
Design patterns for microservice architecture
 
SignalR Overview
SignalR OverviewSignalR Overview
SignalR Overview
 
Retrofit
RetrofitRetrofit
Retrofit
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
JavaScript Programming
JavaScript ProgrammingJavaScript Programming
JavaScript Programming
 
HTML5: features with examples
HTML5: features with examplesHTML5: features with examples
HTML5: features with examples
 
flask.pptx
flask.pptxflask.pptx
flask.pptx
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Flutter talkshow
Flutter talkshowFlutter talkshow
Flutter talkshow
 
Introduction to ParSeq: to make asynchronous java easier
Introduction to ParSeq: to make asynchronous java easierIntroduction to ParSeq: to make asynchronous java easier
Introduction to ParSeq: to make asynchronous java easier
 
Flutter
FlutterFlutter
Flutter
 
CSS Positioning and Features of CSS3
CSS Positioning and Features of CSS3CSS Positioning and Features of CSS3
CSS Positioning and Features of CSS3
 
Kotlin Coroutines Reloaded
Kotlin Coroutines ReloadedKotlin Coroutines Reloaded
Kotlin Coroutines Reloaded
 
Completable future
Completable futureCompletable future
Completable future
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
Html 5
Html 5Html 5
Html 5
 

Semelhante a Asynchronous Programming at Netflix

Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
 	Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W... 	Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
Robert Nyman
 
WebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.jsWebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.js
Robert Nyman
 
mobl presentation @ IHomer
mobl presentation @ IHomermobl presentation @ IHomer
mobl presentation @ IHomer
zefhemel
 
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
Frédéric Harper
 
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobileFirefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Robert Nyman
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
zefhemel
 

Semelhante a Asynchronous Programming at Netflix (20)

Reactive Programming with Rx
 Reactive Programming with Rx Reactive Programming with Rx
Reactive Programming with Rx
 
mobl
moblmobl
mobl
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service Worker
 
Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
 	Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W... 	Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
 
WebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.jsWebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.js
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
mobl presentation @ IHomer
mobl presentation @ IHomermobl presentation @ IHomer
mobl presentation @ IHomer
 
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
 
Firebase & SwiftUI Workshop
Firebase & SwiftUI WorkshopFirebase & SwiftUI Workshop
Firebase & SwiftUI Workshop
 
Firefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobileFirefox OS learnings & visions, WebAPIs - budapest.mobile
Firefox OS learnings & visions, WebAPIs - budapest.mobile
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Minimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team ProductivityMinimizing Decision Fatigue to Improve Team Productivity
Minimizing Decision Fatigue to Improve Team Productivity
 
Google Web Toolkit
Google Web ToolkitGoogle Web Toolkit
Google Web Toolkit
 
Adopting 3D Touch in your apps
Adopting 3D Touch in your appsAdopting 3D Touch in your apps
Adopting 3D Touch in your apps
 
Firefox OS, fixing the mobile web - FITC Toronto - 2014-04-28
Firefox OS, fixing the mobile web - FITC Toronto - 2014-04-28Firefox OS, fixing the mobile web - FITC Toronto - 2014-04-28
Firefox OS, fixing the mobile web - FITC Toronto - 2014-04-28
 
Firefox OS, HTML5 to the next level - Python Montreal - 2014-05-12
Firefox OS, HTML5 to the next level - Python Montreal - 2014-05-12Firefox OS, HTML5 to the next level - Python Montreal - 2014-05-12
Firefox OS, HTML5 to the next level - Python Montreal - 2014-05-12
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widget
 
mobl - model-driven engineering lecture
mobl - model-driven engineering lecturemobl - model-driven engineering lecture
mobl - model-driven engineering lecture
 

Mais de C4Media

Mais de C4Media (20)

Streaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live VideoStreaming a Million Likes/Second: Real-Time Interactions on Live Video
Streaming a Million Likes/Second: Real-Time Interactions on Live Video
 
Next Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy MobileNext Generation Client APIs in Envoy Mobile
Next Generation Client APIs in Envoy Mobile
 
Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020Software Teams and Teamwork Trends Report Q1 2020
Software Teams and Teamwork Trends Report Q1 2020
 
Understand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java ApplicationsUnderstand the Trade-offs Using Compilers for Java Applications
Understand the Trade-offs Using Compilers for Java Applications
 
Kafka Needs No Keeper
Kafka Needs No KeeperKafka Needs No Keeper
Kafka Needs No Keeper
 
High Performing Teams Act Like Owners
High Performing Teams Act Like OwnersHigh Performing Teams Act Like Owners
High Performing Teams Act Like Owners
 
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to JavaDoes Java Need Inline Types? What Project Valhalla Can Bring to Java
Does Java Need Inline Types? What Project Valhalla Can Bring to Java
 
Service Meshes- The Ultimate Guide
Service Meshes- The Ultimate GuideService Meshes- The Ultimate Guide
Service Meshes- The Ultimate Guide
 
Shifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CDShifting Left with Cloud Native CI/CD
Shifting Left with Cloud Native CI/CD
 
CI/CD for Machine Learning
CI/CD for Machine LearningCI/CD for Machine Learning
CI/CD for Machine Learning
 
Fault Tolerance at Speed
Fault Tolerance at SpeedFault Tolerance at Speed
Fault Tolerance at Speed
 
Architectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep SystemsArchitectures That Scale Deep - Regaining Control in Deep Systems
Architectures That Scale Deep - Regaining Control in Deep Systems
 
ML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.jsML in the Browser: Interactive Experiences with Tensorflow.js
ML in the Browser: Interactive Experiences with Tensorflow.js
 
Build Your Own WebAssembly Compiler
Build Your Own WebAssembly CompilerBuild Your Own WebAssembly Compiler
Build Your Own WebAssembly Compiler
 
User & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix ScaleUser & Device Identity for Microservices @ Netflix Scale
User & Device Identity for Microservices @ Netflix Scale
 
Scaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's EdgeScaling Patterns for Netflix's Edge
Scaling Patterns for Netflix's Edge
 
Make Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home EverywhereMake Your Electron App Feel at Home Everywhere
Make Your Electron App Feel at Home Everywhere
 
The Talk You've Been Await-ing For
The Talk You've Been Await-ing ForThe Talk You've Been Await-ing For
The Talk You've Been Await-ing For
 
Future of Data Engineering
Future of Data EngineeringFuture of Data Engineering
Future of Data Engineering
 
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and MoreAutomated Testing for Terraform, Docker, Packer, Kubernetes, and More
Automated Testing for Terraform, Docker, Packer, Kubernetes, and More
 

Último

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Último (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 

Asynchronous Programming at Netflix

  • 1. Async JavaScript at Netflix Jafar Husain @jhusain
  • 2. InfoQ.com: News & Community Site • 750,000 unique visitors/month • Published in 4 languages (English, Chinese, Japanese and Brazilian Portuguese) • Post content from our QCon conferences • News 15-20 / week • Articles 3-4 / week • Presentations (videos) 12-15 / week • Interviews 2-3 / week • Books 1 / month Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations /async-programming-netflix
  • 3. Purpose of QCon - to empower software development by facilitating the spread of knowledge and innovation Strategy - practitioner-driven conference designed for YOU: influencers of change and innovation in your teams - speakers and topics driving the evolution and innovation - connecting and catalyzing the influencers and innovators Highlights - attended by more than 12,000 delegates since 2007 - held in 9 cities worldwide Presented at QCon San Francisco www.qconsf.com
  • 4. Who is Jafar? Cross-Team Technical Lead for Netflix UIs Architect of Netflix UI Data Platform Member of JavaScript standards committee (TC39) 16 years in the industry, formerly worked at Microsoft and GE
  • 5. This is the story of how Netflix solved BIGasync problems by thinking differently about Events.
  • 8. The Netflix App was plagued by Race Conditions Memory Leaks Complex State Machines Uncaught Async Errors
  • 9. Playing a Movie Asynchronously 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(); }); }); 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(); }); });
  • 10. the majority of Netflix’s async code is written with just a few flexible functions. Today
  • 11. But first a brief JavaScript 6 tutorial…
  • 12. Functions x + 1function(x) { return x + 1; }x => function(x, y) { return x + y; }(x, y) x + y=> JS 6 5
  • 13. Fin.
  • 14. ForEach > [1, 2, 3].forEach(x => console.log(x)) > 1 > 2 > 3 >
  • 15. Map
  • 16. Map > [1, 2, 3].map(x => x + 1) > [2, 3, 4] >
  • 18. Filter > [1, 2, 3].filter(x => x > 1) > [2, 3] >
  • 20. concatAll > [ [1], [2, 3], [], [4] ].concatAll() > [1, 2, 3, 4] >
  • 21. 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] >
  • 22.
  • 23. Let’s use map, filter, and concatAll to get a list of your favorite Netflix titles.
  • 24. 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));
  • 25. What if I told you… …that you could create a drag event… …with nearly the same code?
  • 26. 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));
  • 27. Mouse Drags Collection var getElementDrags = elmt => elmt.mouseDowns. map(mouseDown => document.mouseMoves. filter takeUntil(document.mouseUps)). concatAll(); getElementDrags(image). forEach(pos => image.position = pos);
  • 28. “What’s the difference between an Array… [{x: 23, y: 44}, {x:27, y:55}, {x:27, y:55}]
  • 29. … and an Event? {x: 23, y: 44}...{x:27, y:55}.... {x:27, y:55}......
  • 30. Events and Arrays are both collections.
  • 31. So why don’t we program them the same way?
  • 32.
  • 33.
  • 35. 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 } >
  • 36. Map, Filter, and ConcatAll can be implemented using an Iterator.
  • 37. 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 }
  • 38. Iterator Observerprogressively send information to consumer
  • 39. The Iterator and Observer Pattern are Symmetrical.
  • 40.
  • 41. The authors of “Design Patterns” missedthis symmetry.
  • 42. As a result, they gave Iterator and Observer different semantics.
  • 43. So Many Push APIs DOM Events Websockets Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval
  • 44. Observable === Collection + Time Introducing Observable
  • 46. Reactive Extensions Events as Streams Open Source (Apache2) Ported to many languages C .NET JavaScript Java (Netflix) Objective-C
  • 48. Events to Observables var mouseMoves = Observable. fromEvent(element, “mousemove”);
  • 49. Adapt Push APIs to Observable DOM Events Websockets Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable
  • 50. Event Subscription // “subscribe” var handler = (e) => console.log(e); document.addEventListener(“mousemoves”, handler); // “unsubscribe” document.removeEventListener(“mousemoves”, handler);
  • 51. Observable.forEach // “subscribe” var subscription = mouseMoves.forEach(console.log); // “unsubscribe” subscription.dispose();
  • 52. 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
  • 53. 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
  • 54. 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); } }; } }; }
  • 56. ForEach > {1……2…………3}.forEach(console.log) > 1 >> 2 >> 3 > time > {1……2…………3}
  • 57. Map > {1……2…………3}.map(x => x + 1) > 2 >> 3 >> 4 > time
  • 58. > 2 > 3 > Filter > {1……2…………3}.filter(x => x + 1) >> 2 > time
  • 62. Mouse Drags Collection var getElementDrags = elmt => elmt.mouseDowns. map(mouseDown => document.mouseMoves. takeUntil(document.mouseUps)). concatAll(); getElementDrags(image). forEach(pos => image.position = pos);
  • 65. Don’t unsubscribe from Events. Complete them when another event fires.
  • 66. Mouse Drags Collection var getElementDrags = elmt => elmt.mouseDowns. map(mouseDown => document.mouseMoves. takeUntil(document.mouseUps)). concatAll(); getElementDrags(image). forEach(pos => image.position = pos);
  • 68. Netflix Search var 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.”));
  • 69. Netflix Search var 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.”));
  • 70. 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.”));
  • 72. Player Callback Hell 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 = “cancel”; }); if (!player.initialized) { player.init(function(error) { playError = error; tryFinish(); } } authorizeMovie(movieId, function(error, ticket) { playError = error; movieTicket = ticket; tryFinish(); }); });
  • 73. Player with Observable var 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.”));
  • 74. Netflix: Observable Everywhere App Startup Player Data Access Animations View/Model binding
  • 76. 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(); } }
  • 79. Watch the video with slide synchronization on InfoQ.com! http://www.infoq.com/presentations/async- programming-netflix