SlideShare ist ein Scribd-Unternehmen logo
1 von 73
Async Redux Actions With RxJS
… a love story. <3
Ben Lesh
RxJS 5 Lead
Senior Engineer
Netflix UI Platform Team
Twitter: @benlesh
GitHub: blesh
What is redux?
• Red UX – making your whole site red
• A shelter specializing in abandoned pet ducks
• SF startup for bio-engineered foie gras
• An evil recycling program for unwanted ducks
What is redux?
• A library for managing state with reducers
• Basic functional programming wizardry
brought to the masses
• A brilliant piece of work by Dan Abramov (and
many others)
What’s a reducer?
A simple function that takes state
and an action, and returns a new
state
What’s a reducer?
• Sometimes it returns the same state
(state, action) => state
• Sometimes it returns a new state
(state, action) => state + action.value
Reducers in Redux
const reducer = (state = { value: 0 }, action) => {
switch (action.type) {
case ‘INCREMENT’:
return { value: state.value + 1 };
case ‘DECREMENT’:
return { value: state.value – 1 };
default:
return state;
}
};
Reducers are great for managing state!
An action notifies you of a change,
you return a new state! So easy!
Redux reducers handle state
transitions, but they must be
handled synchronously
But what about async?
• User interactions (mouse, keyboard, etc)
• AJAX
• Web Sockets
• Animations
• Workers, et al
A LOT of async results
can be handled synchronously
• Click a button and update a value
• Select an option and update a value
• Get a single AJAX request and update view
• Mouse moves updating some coordinates
Well, some async
is harder than others…
• AJAX cancellation
• Composed AJAX
• Debounced form submissions
• Drag and drop
• Advanced web socket use
What do these “harder” async
stories have in common?
Composing multiple async sources.
…and cancellation!.
In redux, we use middleware to
manage async
Most redux middlewares use
callbacks or promises
Callbacks
The most primitive way to handle asynchrony in
JavaScript is with callbacks
getSomeData((data) => {
dispatch({ type: ‘I_HAVE_DATA’, data });
});
Callback Hell
(aka “the flying V”)
getSomeData(id, (data) => {
dispatch({ type: ‘SOME_DATA’, data });
getSomeData(data.parentId, (parent) => {
dispatch({ type: ‘MORE_DATA’, data });
getSomeData(parent.parentId, (grandparent) => {
dispatch({ type: ‘DATAX3_YOLO_LOL’, data });
});
});
});
Promises provide a cleaner solution
getSomeData(id)
.then(data => {
dispatch({ type: ‘SOME_DATA’, data });
return getSomeData(data.parentId);
})
.then(data => {
dispatch({ type: ‘MORE_DATA’, data });
return getSomeData(data.parentId);
})
.then(data => {
dispatch({ type: ‘DATAX3_YOLO_LOL’, data });
})
Promises
• Guaranteed Future
• Immutable
• Single Value
• Caching
These two features can be problematic
in modern web applications
Promises can’t be cancelled
This means you’re executing code
you don’t want to
Why cancellation is important
• Auto-complete
• Changing views/routes before data finishes
loading
• Tearing down resources
Loading view data without cancellation
Daredevil
Loading view data without cancellation
Daredevil
The Get Down
Since you can’t cancel the previous promise,
you’re stuck processing the response
and somehow signaling “disinterest”
Loading view data without cancellation
Here’s Daredevil!
Daredevil
A better scenario
Daredevil
The Get Down
Ideally, when we make a new request
we can abort the the old one
so it’s never handled and processed
A better scenario
Thanks, Kent C Dodds!
But these days “resources” are
cheap, right?
Netflix targets devices that are 465x
slower than your laptop
Times are changing
• Laptops and desktops are very fast
• Tablets
• Smartphones
• Industrial devices
• SmartTVs
• Appliances
• Wearables
Promises are a single value
Which of these are single value?
• User interactions (mouse, keyboard, etc)
• AJAX
• Web Sockets
• Animations
• Workers, et al
What do we use?
Observables
• A set of events
• Any number of values
• Over any amount of time
• Cancellable
• Lazy
RxJS
Observables and functions to create
and compose Observables
RxJS
“Lodash for async”
RxJS provides many ways to create
Observables
• interval(1000)
• fromEvent(button, ‘click’)
• from([1, 2, 3, 4]);
• of(‘hello’);
• ajax.getJSON(‘http://example.com’);
• webSocket(‘ws://echo.websocket.com’);
• many, many more…
Subscribing to an observable
myObservable.subscribe(x => console.log(x));
Subscribing to an observable
myObservable.subscribe(
x => console.log(x),
err => console.error(err)
);
Subscribing to an observable
myObservable.subscribe(
x => console.log(x),
err => console.error(err) ,
() => console.info(‘complete’)
);
Subscribing to an observable
const subscription = myObservable.subscribe(
x => console.log(x),
err => console.error(err) ,
() => console.info(‘complete’)
);
subscription.unsubscribe();
We have sets of events that we
can cancel!
Okay, now what?
Sets can be transformed
map, filter, reduce
Sets can be combined
concat, merge, zip
Observables are sets with
another dimension: TIME
buffer, throttle, debounce,
combineLatest
Observables are lazy so they can
be resubscribed
retry, repeat
There is an error path, so we can
catch, just like promise
myObservable.catch(err => Observable.of(‘handled’))
You can do just about anything
with RxJS and Observables!
- redux documentation
Well…
Redux has amazing tooling,
community and support around it.
Redux with middleware
provides solid architecture patterns
Async in redux without middleware
Reducer
instance state
handler kicking off async
render
Component
Async in redux with middleware
(and react-redux)
Reducer
Epic
Stateless Component
Let’s combine RxJS and redux!
redux-observable
Epic middleware for redux
What’s an “Epic”?
A function that takes a stream of all actions
dispatched, and returns a stream of actions to
dispatch.
const pingPongEpic = (action$, store) =>
action$.ofType(‘PING’)
.map(action => ({ type: ‘PONG’ });
What’s an “Epic”?
“Actions in, actions out”
const pingPongEpic = (action$, store) =>
action$.ofType(‘PING’)
.map(action => ({ type: ‘PONG’ });
Basic middleware setup
import { createStore, applyMiddlware } from ‘redux’;
import { createEpicMiddleware } from ‘redux-observable’;
import reducerFn, { epicFn } from ‘./redux/updown’;
const epicMiddleware = createEpicMiddleware(epicFn);
const store = createStore(
reducerFn,
applyMiddleware(epicMiddleware)
);
Idiomatic redux increment decrement
with added debounce
const upEpic = (action$, store) =>
action$.ofType(‘UP’)
.debounceTime(1000)
.map(() => ({ type: ‘INCREMENT’ }));
const downEpic = (action$, store) =>
action$.ofType(‘DOWN’)
.debounceTime(1000)
.map(() => ({ type: ‘DECREMENT’ }));
export const updownEpic = combineEpics(upEpic, downEpic);
Idiomatic redux increment decrement
with added debounce
export default const updown = (state = { value: 0 }, action) =>
{
switch (action.type) {
case ‘INCREMENT’:
return { value: state.value + 1 };
case ‘DECREMENT’:
return { value: state.value – 1 };
default:
return state;
}
};
Idiomatic redux increment decrement
with added debounce
WARNING: Don’t read all of this…
Auto-Complete Plain JS
Auto-Complete Epic
export const autoCompleteEpic = (action$, store) =>
action$.ofType(‘LOAD_QUERY’)
.debounceTime(500)
.switchMap(action =>
ajax.getJSON(`http://endpoint/q=${action.value}`)
.map(results => ({ type: ‘QUERY_RESULTS’, results }))
);
compose in cancellation via dispatched
actions
export const autoCompleteEpic = (action$, store) =>
action$.ofType(‘LOAD_QUERY’)
.debounceTime(500)
.switchMap(action =>
ajax.getJSON(`http://endpoint/q=${action.value}`)
.map(results => ({ type: ‘QUERY_RESULTS’, results }))
.takeUntil(action$.ofType(‘CANCEL_QUERY’))
);
Multiplexed Socket Plain JS
Multiplexed Socket Epic
const socket = new WebSocketSubject('ws://stock/endpoint');
const stockTickerEpic = (action$, store) =>
action$.ofType('GET_TICKER_STREAM')
.mergeMap(action =>
socket.multiplex(
() => ({ sub: action.ticker }),
() => ({ unsub: action.ticker }),
msg => msg.ticker === action.ticker
)
.retryWhen(
err => window.navigator.onLine ?
Observable.timer(1000) :
Observable.fromEvent(window, 'online')
)
.takeUntil(
action$.ofType('CLOSE_TICKER_STREAM')
.filter(closeAction => closeAction.ticker === action.ticker)
)
.map(tick => ({ type: 'TICKER_TICK', tick }))
);
The Good
• Makes it very easy to compose and control
complex async tasks with RxJS and redux
• Can use redux tooling
• You don’t end up managing your own Rx
subscriptions
• If used with react-redux, makes all of your
components stateless
The Bad
• Need to know redux in advance
• Should learn RxJS in advance
• RxJS has a bit of a learning curve
redux-observable
https://github.com/redux-observable/redux-observable
Co-Author Jay Phelps
Twitter: @_jayphelps
Github: jayphelps
Thank you!
@benlesh

Weitere ähnliche Inhalte

Was ist angesagt?

Cascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the StreamsCascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the Streamsmattpodwysocki
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術名辰 洪
 
History of jQuery
History of jQueryHistory of jQuery
History of jQueryjeresig
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simplerAlexander Mostovenko
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016Manoj Kumar
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KThomas Fuchs
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptjnewmanux
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the mastersAra Pehlivanian
 
Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was BornDomenic Denicola
 
Luis Atencio on RxJS
Luis Atencio on RxJSLuis Atencio on RxJS
Luis Atencio on RxJSLuis Atencio
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2Jeado Ko
 
Tweaking the interactive grid
Tweaking the interactive gridTweaking the interactive grid
Tweaking the interactive gridRoel Hartman
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureFDConf
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jscacois
 

Was ist angesagt? (20)

Async Frontiers
Async FrontiersAsync Frontiers
Async Frontiers
 
Cascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the StreamsCascadia.js: Don't Cross the Streams
Cascadia.js: Don't Cross the Streams
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術
 
History of jQuery
History of jQueryHistory of jQuery
History of jQuery
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simpler
 
Rxjs kyivjs 2015
Rxjs kyivjs 2015Rxjs kyivjs 2015
Rxjs kyivjs 2015
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 
Rxjs ngvikings
Rxjs ngvikingsRxjs ngvikings
Rxjs ngvikings
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
 
Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was Born
 
Luis Atencio on RxJS
Luis Atencio on RxJSLuis Atencio on RxJS
Luis Atencio on RxJS
 
Reactive, component 그리고 angular2
Reactive, component 그리고  angular2Reactive, component 그리고  angular2
Reactive, component 그리고 angular2
 
XQuery Rocks
XQuery RocksXQuery Rocks
XQuery Rocks
 
Tweaking the interactive grid
Tweaking the interactive gridTweaking the interactive grid
Tweaking the interactive grid
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
 
Avoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.jsAvoiding Callback Hell with Async.js
Avoiding Callback Hell with Async.js
 
Rxjs swetugg
Rxjs swetuggRxjs swetugg
Rxjs swetugg
 

Ähnlich wie Async Redux Actions With RxJS - React Rally 2016

WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...GeeksLab Odessa
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous JavascriptGarrett Welson
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonAlex Payne
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Oscar Renalias
 
RxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptRxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptViliam Elischer
 
Playing With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsPlaying With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsMike Hagedorn
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)Chris Richardson
 
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...Ben Teese
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptGuy Royse
 
How to make Ajax work for you
How to make Ajax work for youHow to make Ajax work for you
How to make Ajax work for youSimon Willison
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
Javascript Everywhere From Nose To Tail
Javascript Everywhere From Nose To TailJavascript Everywhere From Nose To Tail
Javascript Everywhere From Nose To TailCliffano Subagio
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupHenrik Engström
 

Ähnlich wie Async Redux Actions With RxJS - React Rally 2016 (20)

WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the Horizon
 
Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0Asynchronous web apps with the Play Framework 2.0
Asynchronous web apps with the Play Framework 2.0
 
RxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScriptRxJS - The Reactive extensions for JavaScript
RxJS - The Reactive extensions for JavaScript
 
Playing With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.jsPlaying With Fire - An Introduction to Node.js
Playing With Fire - An Introduction to Node.js
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)NodeJS: the good parts? A skeptic’s view (jax jax2013)
NodeJS: the good parts? A skeptic’s view (jax jax2013)
 
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
The Return of JavaScript: 3 Open-Source Projects that are driving JavaScript'...
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScriptjQuery & 10,000 Global Functions: Working with Legacy JavaScript
jQuery & 10,000 Global Functions: Working with Legacy JavaScript
 
How to make Ajax work for you
How to make Ajax work for youHow to make Ajax work for you
How to make Ajax work for you
 
Rxjs marble-testing
Rxjs marble-testingRxjs marble-testing
Rxjs marble-testing
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Yavorsky
YavorskyYavorsky
Yavorsky
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Javascript Everywhere From Nose To Tail
Javascript Everywhere From Nose To TailJavascript Everywhere From Nose To Tail
Javascript Everywhere From Nose To Tail
 
Activator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetupActivator and Reactive at Play NYC meetup
Activator and Reactive at Play NYC meetup
 

Kürzlich hochgeladen

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
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 WorkerThousandEyes
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 

Kürzlich hochgeladen (20)

Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
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
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 

Async Redux Actions With RxJS - React Rally 2016

  • 1.
  • 2. Async Redux Actions With RxJS … a love story. <3
  • 3. Ben Lesh RxJS 5 Lead Senior Engineer Netflix UI Platform Team Twitter: @benlesh GitHub: blesh
  • 4. What is redux? • Red UX – making your whole site red • A shelter specializing in abandoned pet ducks • SF startup for bio-engineered foie gras • An evil recycling program for unwanted ducks
  • 5.
  • 6. What is redux? • A library for managing state with reducers • Basic functional programming wizardry brought to the masses • A brilliant piece of work by Dan Abramov (and many others)
  • 7. What’s a reducer? A simple function that takes state and an action, and returns a new state
  • 8. What’s a reducer? • Sometimes it returns the same state (state, action) => state • Sometimes it returns a new state (state, action) => state + action.value
  • 9. Reducers in Redux const reducer = (state = { value: 0 }, action) => { switch (action.type) { case ‘INCREMENT’: return { value: state.value + 1 }; case ‘DECREMENT’: return { value: state.value – 1 }; default: return state; } };
  • 10. Reducers are great for managing state! An action notifies you of a change, you return a new state! So easy!
  • 11. Redux reducers handle state transitions, but they must be handled synchronously
  • 12. But what about async? • User interactions (mouse, keyboard, etc) • AJAX • Web Sockets • Animations • Workers, et al
  • 13. A LOT of async results can be handled synchronously • Click a button and update a value • Select an option and update a value • Get a single AJAX request and update view • Mouse moves updating some coordinates
  • 14. Well, some async is harder than others… • AJAX cancellation • Composed AJAX • Debounced form submissions • Drag and drop • Advanced web socket use
  • 15. What do these “harder” async stories have in common? Composing multiple async sources. …and cancellation!.
  • 16. In redux, we use middleware to manage async
  • 17. Most redux middlewares use callbacks or promises
  • 18. Callbacks The most primitive way to handle asynchrony in JavaScript is with callbacks getSomeData((data) => { dispatch({ type: ‘I_HAVE_DATA’, data }); });
  • 19. Callback Hell (aka “the flying V”) getSomeData(id, (data) => { dispatch({ type: ‘SOME_DATA’, data }); getSomeData(data.parentId, (parent) => { dispatch({ type: ‘MORE_DATA’, data }); getSomeData(parent.parentId, (grandparent) => { dispatch({ type: ‘DATAX3_YOLO_LOL’, data }); }); }); });
  • 20. Promises provide a cleaner solution getSomeData(id) .then(data => { dispatch({ type: ‘SOME_DATA’, data }); return getSomeData(data.parentId); }) .then(data => { dispatch({ type: ‘MORE_DATA’, data }); return getSomeData(data.parentId); }) .then(data => { dispatch({ type: ‘DATAX3_YOLO_LOL’, data }); })
  • 21. Promises • Guaranteed Future • Immutable • Single Value • Caching These two features can be problematic in modern web applications
  • 22. Promises can’t be cancelled This means you’re executing code you don’t want to
  • 23. Why cancellation is important • Auto-complete • Changing views/routes before data finishes loading • Tearing down resources
  • 24. Loading view data without cancellation
  • 25. Daredevil Loading view data without cancellation
  • 26. Daredevil The Get Down Since you can’t cancel the previous promise, you’re stuck processing the response and somehow signaling “disinterest” Loading view data without cancellation Here’s Daredevil!
  • 28. Daredevil The Get Down Ideally, when we make a new request we can abort the the old one so it’s never handled and processed A better scenario
  • 29. Thanks, Kent C Dodds!
  • 30. But these days “resources” are cheap, right? Netflix targets devices that are 465x slower than your laptop
  • 31. Times are changing • Laptops and desktops are very fast • Tablets • Smartphones • Industrial devices • SmartTVs • Appliances • Wearables
  • 32. Promises are a single value
  • 33. Which of these are single value? • User interactions (mouse, keyboard, etc) • AJAX • Web Sockets • Animations • Workers, et al
  • 34. What do we use?
  • 35. Observables • A set of events • Any number of values • Over any amount of time • Cancellable • Lazy
  • 36. RxJS Observables and functions to create and compose Observables
  • 38. RxJS provides many ways to create Observables • interval(1000) • fromEvent(button, ‘click’) • from([1, 2, 3, 4]); • of(‘hello’); • ajax.getJSON(‘http://example.com’); • webSocket(‘ws://echo.websocket.com’); • many, many more…
  • 39. Subscribing to an observable myObservable.subscribe(x => console.log(x));
  • 40. Subscribing to an observable myObservable.subscribe( x => console.log(x), err => console.error(err) );
  • 41. Subscribing to an observable myObservable.subscribe( x => console.log(x), err => console.error(err) , () => console.info(‘complete’) );
  • 42. Subscribing to an observable const subscription = myObservable.subscribe( x => console.log(x), err => console.error(err) , () => console.info(‘complete’) ); subscription.unsubscribe();
  • 43. We have sets of events that we can cancel! Okay, now what?
  • 44. Sets can be transformed map, filter, reduce
  • 45. Sets can be combined concat, merge, zip
  • 46. Observables are sets with another dimension: TIME buffer, throttle, debounce, combineLatest
  • 47. Observables are lazy so they can be resubscribed retry, repeat
  • 48. There is an error path, so we can catch, just like promise myObservable.catch(err => Observable.of(‘handled’))
  • 49. You can do just about anything with RxJS and Observables!
  • 51. Well… Redux has amazing tooling, community and support around it.
  • 52. Redux with middleware provides solid architecture patterns
  • 53. Async in redux without middleware Reducer instance state handler kicking off async render Component
  • 54. Async in redux with middleware (and react-redux) Reducer Epic Stateless Component
  • 55. Let’s combine RxJS and redux!
  • 57. What’s an “Epic”? A function that takes a stream of all actions dispatched, and returns a stream of actions to dispatch. const pingPongEpic = (action$, store) => action$.ofType(‘PING’) .map(action => ({ type: ‘PONG’ });
  • 58. What’s an “Epic”? “Actions in, actions out” const pingPongEpic = (action$, store) => action$.ofType(‘PING’) .map(action => ({ type: ‘PONG’ });
  • 59. Basic middleware setup import { createStore, applyMiddlware } from ‘redux’; import { createEpicMiddleware } from ‘redux-observable’; import reducerFn, { epicFn } from ‘./redux/updown’; const epicMiddleware = createEpicMiddleware(epicFn); const store = createStore( reducerFn, applyMiddleware(epicMiddleware) );
  • 60. Idiomatic redux increment decrement with added debounce const upEpic = (action$, store) => action$.ofType(‘UP’) .debounceTime(1000) .map(() => ({ type: ‘INCREMENT’ })); const downEpic = (action$, store) => action$.ofType(‘DOWN’) .debounceTime(1000) .map(() => ({ type: ‘DECREMENT’ })); export const updownEpic = combineEpics(upEpic, downEpic);
  • 61. Idiomatic redux increment decrement with added debounce export default const updown = (state = { value: 0 }, action) => { switch (action.type) { case ‘INCREMENT’: return { value: state.value + 1 }; case ‘DECREMENT’: return { value: state.value – 1 }; default: return state; } };
  • 62. Idiomatic redux increment decrement with added debounce
  • 63. WARNING: Don’t read all of this…
  • 65. Auto-Complete Epic export const autoCompleteEpic = (action$, store) => action$.ofType(‘LOAD_QUERY’) .debounceTime(500) .switchMap(action => ajax.getJSON(`http://endpoint/q=${action.value}`) .map(results => ({ type: ‘QUERY_RESULTS’, results })) );
  • 66. compose in cancellation via dispatched actions export const autoCompleteEpic = (action$, store) => action$.ofType(‘LOAD_QUERY’) .debounceTime(500) .switchMap(action => ajax.getJSON(`http://endpoint/q=${action.value}`) .map(results => ({ type: ‘QUERY_RESULTS’, results })) .takeUntil(action$.ofType(‘CANCEL_QUERY’)) );
  • 68. Multiplexed Socket Epic const socket = new WebSocketSubject('ws://stock/endpoint'); const stockTickerEpic = (action$, store) => action$.ofType('GET_TICKER_STREAM') .mergeMap(action => socket.multiplex( () => ({ sub: action.ticker }), () => ({ unsub: action.ticker }), msg => msg.ticker === action.ticker ) .retryWhen( err => window.navigator.onLine ? Observable.timer(1000) : Observable.fromEvent(window, 'online') ) .takeUntil( action$.ofType('CLOSE_TICKER_STREAM') .filter(closeAction => closeAction.ticker === action.ticker) ) .map(tick => ({ type: 'TICKER_TICK', tick })) );
  • 69. The Good • Makes it very easy to compose and control complex async tasks with RxJS and redux • Can use redux tooling • You don’t end up managing your own Rx subscriptions • If used with react-redux, makes all of your components stateless
  • 70. The Bad • Need to know redux in advance • Should learn RxJS in advance • RxJS has a bit of a learning curve
  • 72. Co-Author Jay Phelps Twitter: @_jayphelps Github: jayphelps

Hinweis der Redaktion

  1. Remove mutation?
  2. Have a redux tie-in (dispatch instead of doStuff) note threading of errors
  3. Note promises are only 1 event, this is 0-N.