SlideShare a Scribd company logo
1
Using Redux-Saga for Handling Side Effects
Igor Nesterenko
Lead Software Engineer
17.08.2018
2
Agenda
1. Problem
2. Solutions
3. redux-saga
4. Basic Concepts
5. Advanced Concepts
6. Unit Testing
7. Recommendations
8. Loose Coupled System
9. Summary
10.Future Reading
33
Problem
4
Problem
1. Side-effects are roots of errors and mistrust
• Async (aka concurrency) is hard
2. A program without side effects is useless
3. React and redux don’t solve that all issue
55
Solutions
6
Solutions
1. Custom redux middleware
2. redux-thunk (action creator)
3. redux-saga (saga)
4. redux-loop (reducer)
77
redux-saga
8
redux-saga
1. Origins of Saga Pattern
2. The Process Manager Pattern
3. redux-saga
9
Origins of Saga Pattern
10
Origins of Saga Pattern
Saga is a failure management pattern
● T - transaction
● C - compensation action
11
The Process Manager Pattern
12
The Process Manager
Sagas
ES6 generators
Saga Monitor
redux middleware
Redux Action
13
Confusions around saga pattern
1. Saga is a failure management pattern
2. redux-saga is an alternative side effect model for Redux apps
1414
Basic Concepts
15
Terms
1. Effect - is a single, atomic predefined instruction or command
(POJO)
2. Saga - collection of effects, realized in form of ES6 generator
3. Saga Middleware - redux middleware to execute sagas
4. Effect Creator - function to create effect objects
5. Channels - queues for actions
6. Helper and Untils - helper functions for day to day tasks, factory
function to wrap external IO or event channels
16
Effect and Effect Creator
put({type: 'INCREMENT'}) // => { PUT: {type:
'INCREMENT'} }
call(delay, 1000) // => { CALL: {fn:
delay, args: [1000]}}
17
Effect Creators
● take
● put
● call, apply
● fork, spawn
● cancel, canceled
● select
18
Saga Example
// Our worker Saga: will perform the async increment task
export function* incrementAsync() {
yield delay(1000)
yield put({ type: 'INCREMENT' })
}
19
Setup Saga
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(helloSaga)
const action = type => store.dispatch({type})
20
Synchronous Like Code
function* fetchProducts() {
try {
const products = yield call(Api.fetch, '/products')
yield put({ type: 'PRODUCTS_RECEIVED', products })
}
catch(error) {
yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
} finally {
if (yield cancelled())
yield put({ type: 'PRODUCTS_REQUEST_FAILED', new Error('Canceled')})
}
}
21
Pull Future Action
function* loginFlow() {
while (true) {
yield take('LOGIN')
// ... perform the login logic
yield take('LOGOUT')
// ... perform the logout logic
}
}
2222
Advanced Concepts
23
Advanced Concepts
1. Helper utils
2. Effect Combinators
3. Fork Model
4. Channels
5. External I/O
24
Helper Utils and Effect Creators
export default function* rootSaga() {
yield takeLatest('FETCH_USERS', fetchUsers)
yield takeEvery('CREATE_USER', createUser)
}
25
Effect Combinators
● Run Tasks in Parallel
● Starting Race Between Multiple Tasks
26
Effect Combinators - all
function* fetchAll() {
yield all([
call(fetchResource, 'users'), // task1
call(fetchResource, 'comments'), // task2,
call(delay, 1000)
])
}
27
Effect Combinators - race
function* fetchPostsWithTimeout() {
const {posts, timeout} = yield race({
posts: call(fetchApi, '/posts'),
timeout: call(delay, 1000)
})
if (posts)
put({type: 'POSTS_RECEIVED', posts})
else
put({type: 'TIMEOUT_ERROR'})
}
28
Effect Combinators - Not Only For Requests
function* backgroundTask() {
while (true) { ... }
}
function* watchStartBackgroundTask() {
while (true) {
yield take('START_BACKGROUND_TASK')
yield race({
task: call(backgroundTask),
cancel: take('CANCEL_TASK')
})
}
}
29
Fork Model
● fork is used to create attached fork
● spawn is used to create detached forks
● non-blocking
30
Fork Model
Fetch All
Fetch Comments
Fetch Users
main
Blocking Call
Non-blocking Call
Wait All for Terminate
31
Fork Model - Completion
function* fetchAll() {
const task1 = yield fork(fetchResource, 'users')
const task2 = yield fork(fetchResource, 'comments')
yield call(delay, 1000)
}
function* main() {
yield call(fetchAll)
}
Non-blocking
Blocking
32
Fork Model - Error PropagationFork Model
Fetch All
Fetch Comments
Fetch Users
main
Blocking Call
Non-blocking Call
Catch All Errors Catch Forks Errors
33
Fork Model - Error Propagation
try{
yield fork(watchBgTask);
yield fork(watchCheckout)
} catch (err) {
yield put({type:”CRITICAL_ERROR”});
}
34
Fork Model - Cancelation
function* main() {
while ( yield take(START_BACKGROUND_SYNC) ) {
const bgSyncTask = yield fork(bgSync)
yield take(STOP_BACKGROUND_SYNC)
yield cancel(bgSyncTask)
}
}
35
Fork Model - Detect Cancellation Inside Saga
function* bgSync() {
try {
while (true) {
yield put(actions.requestStart())
const result = yield call(someApi)
yield put(actions.requestSuccess(result))
}
} finally {
if (yield cancelled())
yield put(actions.requestFailure('Sync cancelled!'))
}
}
36
Channels
● Buffer actions from the Redux Store
● Connect take effect to external event source
● Communicate between sagas
37
Channels - Buffer Actions
Saga
F1
Fork
F2
F3
Store
Put 1
Request 1
Request 2
Request 3
Take
Put 2
Put 3
38
Channels - Buffer Actions
function* watchRequests() {
while (true) {
const {payload} = yield take('REQUEST')
yield fork(handleRequest, payload)
}
}
39
Channels - Buffer Actions
Saga StorePut 2
Request 1
Request 2
Request 3
Channel
Put 1
Put 3
Store in Buffer
40
Channels - Buffer Actions
function* watchRequests() {
const requestChan = yield actionChannel('REQUEST')
while (true) {
const {payload} = yield take(requestChan)
yield call(handleRequest, payload)
}
}
41
Channels - Buffer Actions
function* watchRequests() {
const requestChan = yield actionChannel('REQUEST')
while (true) {
const {payload} = yield take(requestChan)
yield call(handleRequest, payload)
}
}
42
Channels - eventChannel
Socket Channel Saga ChanneleventChannel
as argument
creates
My Saga
take, put● emmiter(payload)
● emmiter(END)
43
Channels - eventChannel
export function* watchOnPings() {
const socket = yield call(createWebSocketConnection)
const socketChannel = yield call(createSocketChannel, socket)
while (true) {
const payload = yield take(socketChannel)
yield put({ type: INCOMING_PONG_PAYLOAD, payload })
yield fork(pong, socket)
}
}
44
Channels - eventChannel
function* pong(socket) {
yield call(delay, 5000)
yield apply(socket, socket.emit, ['pong'])
}
45
Channels - Communication Between Sagas
Fork 1
Fork 2
Fork 3
Saga
Shared Channel
aka load balancing
Push message to free fork
create
46
Channels - Communication Between Sagas
function* watchRequests() {
const chan = yield call(channel)
for (var i = 0; i < 3; i++) {
yield fork(handleRequest, chan)
}
while (true) {
const {payload} = yield take('REQUEST')
yield put(chan, payload)
}
}
47
Channels - Communication Between Sagas
function* handleRequest(chan) {
while (true) {
const payload = yield take(chan)
// process the request
}
}
4848
Unit Testing
49
Unit Testing
● Mockless unit testing
● Saga Helpers
50
Unit Testing - Iterate and Compare
function* incrementAsync() {
yield delay(1000)
yield put({ type: 'INCREMENT' })
}
51
Unit Testing - Iterate and Compare
test('incrementAsync Saga test', (assert) => {
const gen = incrementAsync()
// now what ?
});
52
Unit Testing - Iterate and Compare
gen.next() //=>{ done: false, value: <result ... delay(1000)> }
gen.next() //=>{ done: false, value: <result ... put({...})> }
gen.next() //=>{ done: true, value: undefined }
53
Unit Testing - Iterate and Compare
test('incrementAsync Saga test', (assert) => {
const gen = incrementAsync()
assert.deepEqual(
gen.next().value,
call(delay, 1000),
'incrementAsync Saga must call delay(1000)'
)
// ....
});
54
Unit Testing - Different Branches
function* doStuffThenChangeColor() {
yield put(doStuff());
yield put(doStuff());
const action = yield take(CHOOSE_NUMBER);
if (action.payload.number % 2 === 0) {
yield put(changeUI('red'));
} else {
yield put(changeUI('blue'));
}
}
55
Unit Testing - Clonable Generator
test('doStuffThenChangeColor', assert => {
const gen = cloneableGenerator(doStuffThenChangeColor)();
gen.next(); // DO_STUFF
gen.next(); // DO_STUFF
gen.next(); // CHOOSE_NUMBER
// ...
});
56
Unit Testing - Clonable Generator - First Branch
const gen = cloneableGenerator(doStuffThenChangeColor)();
// ...
const clone = gen.clone();
assert.deepEqual(
clone.next(chooseNumber(2)).value,
put(changeUI('red')),
'should change the color to red'
);
57
Unit Testing - Clonable Generator - Second Branch
const gen = cloneableGenerator(doStuffThenChangeColor)();
// ...
const otherClone = gen.clone();
assert.deepEqual(
otherClone.next(chooseNumber(3)).value,
put(changeUI('blue')),
'should change the color to blue'
);
58
Unit Testing - Clonable Generator
test('doStuffThenChangeColor', assert => {
const gen = cloneableGenerator(doStuffThenChangeColor)();
gen.next(); // DO_STUFF
gen.next(); // DO_STUFF
gen.next(); // CHOOSE_NUMBER
// ...
});
59
Unit Testing - Fork Effect
function* main() {
while ( yield take(START_BACKGROUND_SYNC) ) {
const bgSyncTask = yield fork(bgSync)
yield take(STOP_BACKGROUND_SYNC)
yield cancel(bgSyncTask)
}
}
60
Unit Testing - Fork Effect
expect(generator.next().value).toEqual(take(START_BG_SYNC));
expect(generator.next({ type: 'START_BG_SYNC' }).value).toEqual(fork(bgSync));
const mockTask = createMockTask();
expect(generator.next(mockTask).value).toEqual(take(STOP_BACKGROUND_SYNC));
expect(generator.next().value).toEqual(cancel(mockTask));
6161
Recommendations
62
Recommendations
1. Code Smells
2. Integration with React Component
3. Identify Core Flows
4. Invest in error-handling
5. Extract Reusable Saga
6. Unit Testing strategy
63
Code Smells
1.Avoid Routing
2.Avoid Reducer Logic
64
Code Smells - Routing in Sagas
// ...
import { push } from 'react-router-redux';
export default function* handleProductRedirect() {
const productId = yield select(getRouterProductId);
yield put(push(`/checkout/product/${productId}`));
}
65
Code Smells - Reducer Logic in Sagas
export function* watchForSomething() {
while (true) {
const {payload: {oneThing, anotherThing}} = yield take(SOME_THING);
yield put(DO_ONE_THING, oneThing);
yield put(DO_ANOTHER_THING, anotherThing);
}
}
66
Code Smells - Reducer Logic in Sagas
● Data Massaging
● switch for action.type ...
● Something other then Side-Effect
67
Extract Reusable Saga
export default function standartRequest(request, success, failure) {
return function* requestHandlingSaga(action) {
try {
const response = yield call(request, action.payload);
yield put(success(response));
} catch (error) {
yield put(failure(error));
}
};
}
68
Extract Reusable Saga
const handleEntityRequest = standartRequest(
Api.fetchEntity
ENTITY_REQUEST_SUCCESS,
ENTITY_REQUEST_ERROR
)
69
Integration with React Component
● componentDidMount - initialize sub-flow
● componentWillUnmount - teardown sub-flow
● Combine with Routing
● Sync with bootstrap of application
70
Combine With Routing
• /entities/ -> EntitiesRoute - dispatch list request
• /entities/ -> EntitiesList
• /entities/:id -> EntityRoute - dispatch single entity
●/entities/:id -> Entity
●/entities/:id/edit -> EntityEdit - dispatch save
71
Combine With Routing
export default function* watchEntities() {
yield takeLatest(ENTITES_REQUEST,handleEntitiesRequest);
yield takeLatest(ENTITY_REQUEST,handleEntityRequest);
yield takeLatest(ENTITY_SAVE_REQUEST,handleEntitySaveRequest);
}
72
Sync with Application Bootstrap
export default function* watchEntities() {
yield takeLatest(ENTITES_REQUEST, runAfterAuth(handleEntitysRequest)),
yield takeLatest(ENTITY_REQUEST, runAfterAuth(handleEntityRequest));
yield takeLatest(ENTITY_SAVE_REQUEST, handleEntitySaveRequest);
}
73
Sync with Application Bootstrap
export default function* runAfterAuth(handler) {
return function* (action){
const isAuthenticated = yield select(isAppAuthDone);
if (!isAuthenticated) {
yield take(APP_AUTH_SUCCESS);
}
yield call(handler, action)
}
}
74
Invest in Error Handling
1. Acton Error Naming Convention
• like “*_ERROR” postfix in actions naming
2. Unified way to make requests, I/O
3. Logger and some UI to show error to the user
75
Error Handling
export default function* rootSaga() {
try {
yield all([
watchAuth(),
watchEntities()
])
} catch (e) {
logger.error(e);
yield put(errorCritical(e));
}
}
76
Issues with stacktrace
77
babel-plugin-redux-saga
78
Unit Testing Strategy
1. Start from covering top flows for example
• must have watchAuth, watchCheckout
• nice to have watchEntities
2. Cover reusable sagas like standartRequest, runAfterAuth
7979
Loose Coupling
80
Coupling
8181
Summary
82
Summary
1. Inspired by Saga pattern, however it’s not exact implementation of Saga
pattern
2. Provides constraints to handle side-effects in one place
3. Allows maintainable unit testing of side-effect (without mocking)
4. Saga works great for side-effects, but produces code smells if used for
other tasks like routing, data massaging (aka reducers logic)
8383
Future Reading
84
Future Reading
● Origins
○ Sagas - original paper
○ Confusion about Saga pattern
○ Clarifying the Saga pattern
○ Communicating Sequential Processes
● redux-saga
○ Saga ? Why not CSP ?
○ External Resources
● Other Domains
○ Applying Saga Pattern
○ Sagas
● Unit Testing
○ Mocking is a Code Smell
85
Questions ?
86
Thank you
8787
Side Effects
88
Side-Effects
● State/Assignments
● Read/Write Data
● Communicate Over Network
● Raise Exception
● DOM
In computer science, a function or expression is said to have a
side effect if, in addition to producing a value, it also modifies
some state or has an observable interaction with calling
functions or the outside world
89
Give Me a Label
const label = await this.getLabel();
90
May Launch Missiles
async function getLabel () {
const val = Math.random();
if (val > 0.5){
await launchMissles();
return `foo foo ${val}`
}
return `blah blah ${val}`;
}
91
Why should I care about side effects ?
“Side effects are lies. Your function promises to do one thing,
but it also does other hidden things...they are devious and
damaging mistruths that often result in strange temporal
couplings and order dependencies.”
Clean Code, Robert Martin
92
Things to remember
● A program without side effects is useless
● Side effects are neither evil nor taboo
● The key is to
○ limit side effects
○ clearly identify them
○ avoid scattering them throughout the code.
93
Minuses
● issues with stacktrace
● more boilerplate code
● structuring sagas
● learning curve
94
Pluses
● side-effects isolated in one place
● maintainable code (unit testable)
● loosely coupled system
9595
Saga Pitch
96
Basics Concepts
1. Separate Instructions from Execution
2. Use ES6 generator to define set of instructions
3. Use redux middleware to execute instructions
4. Execution works with `pull-future-actions` approach
97
Saga
1. Improve Loose Coupling (SR, Component and Actions)
2. Something on top of async/await, Observables
3. Maintainable Unit Testing (without mocks)
4. Makes important business flows explicitly defined in code
5. More explicit error handling techniques
Ad

More Related Content

What's hot (20)

VB Script
VB ScriptVB Script
VB Script
Satish Sukumaran
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
Ignacio Martín
 
Vue and React Comparison
Vue and React ComparisonVue and React Comparison
Vue and React Comparison
Viet Tran
 
Sagas Middleware Architecture
Sagas Middleware ArchitectureSagas Middleware Architecture
Sagas Middleware Architecture
Mateusz Bosek
 
Redux Thunk
Redux ThunkRedux Thunk
Redux Thunk
ASIMYILDIZ
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
L&T Technology Services Limited
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
Visual Engineering
 
Build Your Own Angular Component Library
Build Your Own Angular Component LibraryBuild Your Own Angular Component Library
Build Your Own Angular Component Library
Carlo Bonamico
 
Bootstrap.pptx
Bootstrap.pptxBootstrap.pptx
Bootstrap.pptx
vishal choudhary
 
Introduction to web programming with JavaScript
Introduction to web programming with JavaScriptIntroduction to web programming with JavaScript
Introduction to web programming with JavaScript
T11 Sessions
 
How to Automate API Testing
How to Automate API TestingHow to Automate API Testing
How to Automate API Testing
Bruno Pedro
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS Directives
Eyal Vardi
 
React-JS Component Life-cycle Methods
React-JS Component Life-cycle MethodsReact-JS Component Life-cycle Methods
React-JS Component Life-cycle Methods
ANKUSH CHAVAN
 
Express js
Express jsExpress js
Express js
Manav Prasad
 
Rust
RustRust
Rust
Chih-Hsuan Kuo
 
Workshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux AdvancedWorkshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux Advanced
Visual Engineering
 
Rest presentation
Rest  presentationRest  presentation
Rest presentation
srividhyau
 
React js programming concept
React js programming conceptReact js programming concept
React js programming concept
Tariqul islam
 
Learning RSocket Using RSC
Learning RSocket Using RSCLearning RSocket Using RSC
Learning RSocket Using RSC
VMware Tanzu
 
JavaScript Basics and Best Practices - CC FE & UX
JavaScript Basics and Best Practices - CC FE & UXJavaScript Basics and Best Practices - CC FE & UX
JavaScript Basics and Best Practices - CC FE & UX
JWORKS powered by Ordina
 
Vue and React Comparison
Vue and React ComparisonVue and React Comparison
Vue and React Comparison
Viet Tran
 
Sagas Middleware Architecture
Sagas Middleware ArchitectureSagas Middleware Architecture
Sagas Middleware Architecture
Mateusz Bosek
 
Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.Workshop 4: NodeJS. Express Framework & MongoDB.
Workshop 4: NodeJS. Express Framework & MongoDB.
Visual Engineering
 
Build Your Own Angular Component Library
Build Your Own Angular Component LibraryBuild Your Own Angular Component Library
Build Your Own Angular Component Library
Carlo Bonamico
 
Introduction to web programming with JavaScript
Introduction to web programming with JavaScriptIntroduction to web programming with JavaScript
Introduction to web programming with JavaScript
T11 Sessions
 
How to Automate API Testing
How to Automate API TestingHow to Automate API Testing
How to Automate API Testing
Bruno Pedro
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS Directives
Eyal Vardi
 
React-JS Component Life-cycle Methods
React-JS Component Life-cycle MethodsReact-JS Component Life-cycle Methods
React-JS Component Life-cycle Methods
ANKUSH CHAVAN
 
Workshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux AdvancedWorkshop 22: ReactJS Redux Advanced
Workshop 22: ReactJS Redux Advanced
Visual Engineering
 
Rest presentation
Rest  presentationRest  presentation
Rest presentation
srividhyau
 
React js programming concept
React js programming conceptReact js programming concept
React js programming concept
Tariqul islam
 
Learning RSocket Using RSC
Learning RSocket Using RSCLearning RSocket Using RSC
Learning RSocket Using RSC
VMware Tanzu
 
JavaScript Basics and Best Practices - CC FE & UX
JavaScript Basics and Best Practices - CC FE & UXJavaScript Basics and Best Practices - CC FE & UX
JavaScript Basics and Best Practices - CC FE & UX
JWORKS powered by Ordina
 

Similar to Using Redux-Saga for Handling Side Effects (20)

Side effects-con-redux
Side effects-con-reduxSide effects-con-redux
Side effects-con-redux
Nicolas Quiceno Benavides
 
Curator intro
Curator introCurator intro
Curator intro
Jordan Zimmerman
 
Road to react hooks
Road to react hooksRoad to react hooks
Road to react hooks
Younes (omar) Meliani
 
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Codemotion
 
Asyc flow control with javascript generators - redux-saga
Asyc flow control with javascript generators - redux-sagaAsyc flow control with javascript generators - redux-saga
Asyc flow control with javascript generators - redux-saga
Pedro Solá
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
Ankit Rastogi
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
Thierry Wasylczenko
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
knight1128
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
Greg Bergé
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applications
Evangelia Mitsopoulou
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 
What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)
What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)
What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)
DicodingEvent
 
Douglas Crockford: Serversideness
Douglas Crockford: ServersidenessDouglas Crockford: Serversideness
Douglas Crockford: Serversideness
WebExpo
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
Vadym Khondar
 
Redux Deep Dive - ReactFoo Pune 2018
Redux Deep Dive - ReactFoo Pune 2018Redux Deep Dive - ReactFoo Pune 2018
Redux Deep Dive - ReactFoo Pune 2018
Aziz Khambati
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
Pavan Chitumalla
 
Android Loaders : Reloaded
Android Loaders : ReloadedAndroid Loaders : Reloaded
Android Loaders : Reloaded
cbeyls
 
React. Redux. Real world.
React. Redux. Real world.React. Redux. Real world.
React. Redux. Real world.
Rost Galkin
 
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Ontico
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
Bo-Yi Wu
 
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Matteo Collina | Take your HTTP server to Ludicrous Speed | Codmeotion Madrid...
Codemotion
 
Asyc flow control with javascript generators - redux-saga
Asyc flow control with javascript generators - redux-sagaAsyc flow control with javascript generators - redux-saga
Asyc flow control with javascript generators - redux-saga
Pedro Solá
 
Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
Ankit Rastogi
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
Thierry Wasylczenko
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
knight1128
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
Greg Bergé
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applications
Evangelia Mitsopoulou
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 
What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)
What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)
What's new in WorkManager-Andri Suranta Ginting (Product Engineer-Gojek)
DicodingEvent
 
Douglas Crockford: Serversideness
Douglas Crockford: ServersidenessDouglas Crockford: Serversideness
Douglas Crockford: Serversideness
WebExpo
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
Vadym Khondar
 
Redux Deep Dive - ReactFoo Pune 2018
Redux Deep Dive - ReactFoo Pune 2018Redux Deep Dive - ReactFoo Pune 2018
Redux Deep Dive - ReactFoo Pune 2018
Aziz Khambati
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
Pavan Chitumalla
 
Android Loaders : Reloaded
Android Loaders : ReloadedAndroid Loaders : Reloaded
Android Loaders : Reloaded
cbeyls
 
React. Redux. Real world.
React. Redux. Real world.React. Redux. Real world.
React. Redux. Real world.
Rost Galkin
 
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Amazing threesome, rrr... React. Redux. Real world / Ростислав Галкин (Babo)
Ontico
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
Bo-Yi Wu
 
Ad

More from GlobalLogic Ukraine (20)

GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic Ukraine
 
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Ukraine
 
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Ukraine
 
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic Ukraine
 
Штучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptxШтучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptx
GlobalLogic Ukraine
 
Задачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptxЗадачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptx
GlobalLogic Ukraine
 
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptxЩо треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Ukraine
 
JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"
GlobalLogic Ukraine
 
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic Ukraine
 
Страх і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic EducationСтрах і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic Education
GlobalLogic Ukraine
 
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic Ukraine
 
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic Ukraine
 
“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Ukraine
 
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic Ukraine
 
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
GlobalLogic Ukraine
 
GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic JavaScript Community Webinar #21 “Інтерв’ю без заспокійливих”
GlobalLogic Ukraine
 
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
Deadlocks in SQL - Turning Fear Into Understanding (by Sergii Stets)
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Java Community Webinar #18 “How to Improve Web Application Perfor...
GlobalLogic Ukraine
 
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Embedded Community x ROS Ukraine Webinar "Surgical Robots"
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Java Community Webinar #17 “SpringJDBC vs JDBC. Is Spring a Hero?”
GlobalLogic Ukraine
 
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic JavaScript Community Webinar #18 “Long Story Short: OSI Model”
GlobalLogic Ukraine
 
Штучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptxШтучний інтелект як допомога в навчанні, а не замінник.pptx
Штучний інтелект як допомога в навчанні, а не замінник.pptx
GlobalLogic Ukraine
 
Задачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptxЗадачі AI-розробника як застосовується штучний інтелект.pptx
Задачі AI-розробника як застосовується штучний інтелект.pptx
GlobalLogic Ukraine
 
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptxЩо треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
Що треба вивчати, щоб стати розробником штучного інтелекту та нейромереж.pptx
GlobalLogic Ukraine
 
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Java Community Webinar #16 “Zaloni’s Architecture for Data-Driven...
GlobalLogic Ukraine
 
JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"JavaScript Community Webinar #14 "Why Is Git Rebase?"
JavaScript Community Webinar #14 "Why Is Git Rebase?"
GlobalLogic Ukraine
 
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic .NET Community Webinar #3 "Exploring Serverless with Azure Functi...
GlobalLogic Ukraine
 
Страх і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic EducationСтрах і сила помилок - IT Inside від GlobalLogic Education
Страх і сила помилок - IT Inside від GlobalLogic Education
GlobalLogic Ukraine
 
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic .NET Webinar #2 “Azure RBAC and Managed Identity”
GlobalLogic Ukraine
 
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic QA Webinar “What does it take to become a Test Engineer”
GlobalLogic Ukraine
 
“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?“How to Secure Your Applications With a Keycloak?
“How to Secure Your Applications With a Keycloak?
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Machine Learning Webinar “Advanced Statistical Methods for Linear...
GlobalLogic Ukraine
 
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Machine Learning Webinar “Statistical learning of linear regressi...
GlobalLogic Ukraine
 
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic C++ Webinar “The Minimum Knowledge to Become a C++ Developer”
GlobalLogic Ukraine
 
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
Embedded Webinar #17 "Low-level Network Testing in Embedded Devices Development"
GlobalLogic Ukraine
 
Ad

Recently uploaded (20)

Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025Splunk Security Update | Public Sector Summit Germany 2025
Splunk Security Update | Public Sector Summit Germany 2025
Splunk
 
Semantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AISemantic Cultivators : The Critical Future Role to Enable AI
Semantic Cultivators : The Critical Future Role to Enable AI
artmondano
 
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
Transcript: #StandardsGoals for 2025: Standards & certification roundup - Tec...
BookNet Canada
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
IEDM 2024 Tutorial2_Advances in CMOS Technologies and Future Directions for C...
organizerofv
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Rusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond SparkRusty Waters: Elevating Lakehouses Beyond Spark
Rusty Waters: Elevating Lakehouses Beyond Spark
carlyakerly1
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 

Using Redux-Saga for Handling Side Effects

  • 1. 1 Using Redux-Saga for Handling Side Effects Igor Nesterenko Lead Software Engineer 17.08.2018
  • 2. 2 Agenda 1. Problem 2. Solutions 3. redux-saga 4. Basic Concepts 5. Advanced Concepts 6. Unit Testing 7. Recommendations 8. Loose Coupled System 9. Summary 10.Future Reading
  • 4. 4 Problem 1. Side-effects are roots of errors and mistrust • Async (aka concurrency) is hard 2. A program without side effects is useless 3. React and redux don’t solve that all issue
  • 6. 6 Solutions 1. Custom redux middleware 2. redux-thunk (action creator) 3. redux-saga (saga) 4. redux-loop (reducer)
  • 8. 8 redux-saga 1. Origins of Saga Pattern 2. The Process Manager Pattern 3. redux-saga
  • 10. 10 Origins of Saga Pattern Saga is a failure management pattern ● T - transaction ● C - compensation action
  • 12. 12 The Process Manager Sagas ES6 generators Saga Monitor redux middleware Redux Action
  • 13. 13 Confusions around saga pattern 1. Saga is a failure management pattern 2. redux-saga is an alternative side effect model for Redux apps
  • 15. 15 Terms 1. Effect - is a single, atomic predefined instruction or command (POJO) 2. Saga - collection of effects, realized in form of ES6 generator 3. Saga Middleware - redux middleware to execute sagas 4. Effect Creator - function to create effect objects 5. Channels - queues for actions 6. Helper and Untils - helper functions for day to day tasks, factory function to wrap external IO or event channels
  • 16. 16 Effect and Effect Creator put({type: 'INCREMENT'}) // => { PUT: {type: 'INCREMENT'} } call(delay, 1000) // => { CALL: {fn: delay, args: [1000]}}
  • 17. 17 Effect Creators ● take ● put ● call, apply ● fork, spawn ● cancel, canceled ● select
  • 18. 18 Saga Example // Our worker Saga: will perform the async increment task export function* incrementAsync() { yield delay(1000) yield put({ type: 'INCREMENT' }) }
  • 19. 19 Setup Saga const sagaMiddleware = createSagaMiddleware() const store = createStore( reducer, applyMiddleware(sagaMiddleware) ) sagaMiddleware.run(helloSaga) const action = type => store.dispatch({type})
  • 20. 20 Synchronous Like Code function* fetchProducts() { try { const products = yield call(Api.fetch, '/products') yield put({ type: 'PRODUCTS_RECEIVED', products }) } catch(error) { yield put({ type: 'PRODUCTS_REQUEST_FAILED', error }) } finally { if (yield cancelled()) yield put({ type: 'PRODUCTS_REQUEST_FAILED', new Error('Canceled')}) } }
  • 21. 21 Pull Future Action function* loginFlow() { while (true) { yield take('LOGIN') // ... perform the login logic yield take('LOGOUT') // ... perform the logout logic } }
  • 23. 23 Advanced Concepts 1. Helper utils 2. Effect Combinators 3. Fork Model 4. Channels 5. External I/O
  • 24. 24 Helper Utils and Effect Creators export default function* rootSaga() { yield takeLatest('FETCH_USERS', fetchUsers) yield takeEvery('CREATE_USER', createUser) }
  • 25. 25 Effect Combinators ● Run Tasks in Parallel ● Starting Race Between Multiple Tasks
  • 26. 26 Effect Combinators - all function* fetchAll() { yield all([ call(fetchResource, 'users'), // task1 call(fetchResource, 'comments'), // task2, call(delay, 1000) ]) }
  • 27. 27 Effect Combinators - race function* fetchPostsWithTimeout() { const {posts, timeout} = yield race({ posts: call(fetchApi, '/posts'), timeout: call(delay, 1000) }) if (posts) put({type: 'POSTS_RECEIVED', posts}) else put({type: 'TIMEOUT_ERROR'}) }
  • 28. 28 Effect Combinators - Not Only For Requests function* backgroundTask() { while (true) { ... } } function* watchStartBackgroundTask() { while (true) { yield take('START_BACKGROUND_TASK') yield race({ task: call(backgroundTask), cancel: take('CANCEL_TASK') }) } }
  • 29. 29 Fork Model ● fork is used to create attached fork ● spawn is used to create detached forks ● non-blocking
  • 30. 30 Fork Model Fetch All Fetch Comments Fetch Users main Blocking Call Non-blocking Call Wait All for Terminate
  • 31. 31 Fork Model - Completion function* fetchAll() { const task1 = yield fork(fetchResource, 'users') const task2 = yield fork(fetchResource, 'comments') yield call(delay, 1000) } function* main() { yield call(fetchAll) } Non-blocking Blocking
  • 32. 32 Fork Model - Error PropagationFork Model Fetch All Fetch Comments Fetch Users main Blocking Call Non-blocking Call Catch All Errors Catch Forks Errors
  • 33. 33 Fork Model - Error Propagation try{ yield fork(watchBgTask); yield fork(watchCheckout) } catch (err) { yield put({type:”CRITICAL_ERROR”}); }
  • 34. 34 Fork Model - Cancelation function* main() { while ( yield take(START_BACKGROUND_SYNC) ) { const bgSyncTask = yield fork(bgSync) yield take(STOP_BACKGROUND_SYNC) yield cancel(bgSyncTask) } }
  • 35. 35 Fork Model - Detect Cancellation Inside Saga function* bgSync() { try { while (true) { yield put(actions.requestStart()) const result = yield call(someApi) yield put(actions.requestSuccess(result)) } } finally { if (yield cancelled()) yield put(actions.requestFailure('Sync cancelled!')) } }
  • 36. 36 Channels ● Buffer actions from the Redux Store ● Connect take effect to external event source ● Communicate between sagas
  • 37. 37 Channels - Buffer Actions Saga F1 Fork F2 F3 Store Put 1 Request 1 Request 2 Request 3 Take Put 2 Put 3
  • 38. 38 Channels - Buffer Actions function* watchRequests() { while (true) { const {payload} = yield take('REQUEST') yield fork(handleRequest, payload) } }
  • 39. 39 Channels - Buffer Actions Saga StorePut 2 Request 1 Request 2 Request 3 Channel Put 1 Put 3 Store in Buffer
  • 40. 40 Channels - Buffer Actions function* watchRequests() { const requestChan = yield actionChannel('REQUEST') while (true) { const {payload} = yield take(requestChan) yield call(handleRequest, payload) } }
  • 41. 41 Channels - Buffer Actions function* watchRequests() { const requestChan = yield actionChannel('REQUEST') while (true) { const {payload} = yield take(requestChan) yield call(handleRequest, payload) } }
  • 42. 42 Channels - eventChannel Socket Channel Saga ChanneleventChannel as argument creates My Saga take, put● emmiter(payload) ● emmiter(END)
  • 43. 43 Channels - eventChannel export function* watchOnPings() { const socket = yield call(createWebSocketConnection) const socketChannel = yield call(createSocketChannel, socket) while (true) { const payload = yield take(socketChannel) yield put({ type: INCOMING_PONG_PAYLOAD, payload }) yield fork(pong, socket) } }
  • 44. 44 Channels - eventChannel function* pong(socket) { yield call(delay, 5000) yield apply(socket, socket.emit, ['pong']) }
  • 45. 45 Channels - Communication Between Sagas Fork 1 Fork 2 Fork 3 Saga Shared Channel aka load balancing Push message to free fork create
  • 46. 46 Channels - Communication Between Sagas function* watchRequests() { const chan = yield call(channel) for (var i = 0; i < 3; i++) { yield fork(handleRequest, chan) } while (true) { const {payload} = yield take('REQUEST') yield put(chan, payload) } }
  • 47. 47 Channels - Communication Between Sagas function* handleRequest(chan) { while (true) { const payload = yield take(chan) // process the request } }
  • 49. 49 Unit Testing ● Mockless unit testing ● Saga Helpers
  • 50. 50 Unit Testing - Iterate and Compare function* incrementAsync() { yield delay(1000) yield put({ type: 'INCREMENT' }) }
  • 51. 51 Unit Testing - Iterate and Compare test('incrementAsync Saga test', (assert) => { const gen = incrementAsync() // now what ? });
  • 52. 52 Unit Testing - Iterate and Compare gen.next() //=>{ done: false, value: <result ... delay(1000)> } gen.next() //=>{ done: false, value: <result ... put({...})> } gen.next() //=>{ done: true, value: undefined }
  • 53. 53 Unit Testing - Iterate and Compare test('incrementAsync Saga test', (assert) => { const gen = incrementAsync() assert.deepEqual( gen.next().value, call(delay, 1000), 'incrementAsync Saga must call delay(1000)' ) // .... });
  • 54. 54 Unit Testing - Different Branches function* doStuffThenChangeColor() { yield put(doStuff()); yield put(doStuff()); const action = yield take(CHOOSE_NUMBER); if (action.payload.number % 2 === 0) { yield put(changeUI('red')); } else { yield put(changeUI('blue')); } }
  • 55. 55 Unit Testing - Clonable Generator test('doStuffThenChangeColor', assert => { const gen = cloneableGenerator(doStuffThenChangeColor)(); gen.next(); // DO_STUFF gen.next(); // DO_STUFF gen.next(); // CHOOSE_NUMBER // ... });
  • 56. 56 Unit Testing - Clonable Generator - First Branch const gen = cloneableGenerator(doStuffThenChangeColor)(); // ... const clone = gen.clone(); assert.deepEqual( clone.next(chooseNumber(2)).value, put(changeUI('red')), 'should change the color to red' );
  • 57. 57 Unit Testing - Clonable Generator - Second Branch const gen = cloneableGenerator(doStuffThenChangeColor)(); // ... const otherClone = gen.clone(); assert.deepEqual( otherClone.next(chooseNumber(3)).value, put(changeUI('blue')), 'should change the color to blue' );
  • 58. 58 Unit Testing - Clonable Generator test('doStuffThenChangeColor', assert => { const gen = cloneableGenerator(doStuffThenChangeColor)(); gen.next(); // DO_STUFF gen.next(); // DO_STUFF gen.next(); // CHOOSE_NUMBER // ... });
  • 59. 59 Unit Testing - Fork Effect function* main() { while ( yield take(START_BACKGROUND_SYNC) ) { const bgSyncTask = yield fork(bgSync) yield take(STOP_BACKGROUND_SYNC) yield cancel(bgSyncTask) } }
  • 60. 60 Unit Testing - Fork Effect expect(generator.next().value).toEqual(take(START_BG_SYNC)); expect(generator.next({ type: 'START_BG_SYNC' }).value).toEqual(fork(bgSync)); const mockTask = createMockTask(); expect(generator.next(mockTask).value).toEqual(take(STOP_BACKGROUND_SYNC)); expect(generator.next().value).toEqual(cancel(mockTask));
  • 62. 62 Recommendations 1. Code Smells 2. Integration with React Component 3. Identify Core Flows 4. Invest in error-handling 5. Extract Reusable Saga 6. Unit Testing strategy
  • 64. 64 Code Smells - Routing in Sagas // ... import { push } from 'react-router-redux'; export default function* handleProductRedirect() { const productId = yield select(getRouterProductId); yield put(push(`/checkout/product/${productId}`)); }
  • 65. 65 Code Smells - Reducer Logic in Sagas export function* watchForSomething() { while (true) { const {payload: {oneThing, anotherThing}} = yield take(SOME_THING); yield put(DO_ONE_THING, oneThing); yield put(DO_ANOTHER_THING, anotherThing); } }
  • 66. 66 Code Smells - Reducer Logic in Sagas ● Data Massaging ● switch for action.type ... ● Something other then Side-Effect
  • 67. 67 Extract Reusable Saga export default function standartRequest(request, success, failure) { return function* requestHandlingSaga(action) { try { const response = yield call(request, action.payload); yield put(success(response)); } catch (error) { yield put(failure(error)); } }; }
  • 68. 68 Extract Reusable Saga const handleEntityRequest = standartRequest( Api.fetchEntity ENTITY_REQUEST_SUCCESS, ENTITY_REQUEST_ERROR )
  • 69. 69 Integration with React Component ● componentDidMount - initialize sub-flow ● componentWillUnmount - teardown sub-flow ● Combine with Routing ● Sync with bootstrap of application
  • 70. 70 Combine With Routing • /entities/ -> EntitiesRoute - dispatch list request • /entities/ -> EntitiesList • /entities/:id -> EntityRoute - dispatch single entity ●/entities/:id -> Entity ●/entities/:id/edit -> EntityEdit - dispatch save
  • 71. 71 Combine With Routing export default function* watchEntities() { yield takeLatest(ENTITES_REQUEST,handleEntitiesRequest); yield takeLatest(ENTITY_REQUEST,handleEntityRequest); yield takeLatest(ENTITY_SAVE_REQUEST,handleEntitySaveRequest); }
  • 72. 72 Sync with Application Bootstrap export default function* watchEntities() { yield takeLatest(ENTITES_REQUEST, runAfterAuth(handleEntitysRequest)), yield takeLatest(ENTITY_REQUEST, runAfterAuth(handleEntityRequest)); yield takeLatest(ENTITY_SAVE_REQUEST, handleEntitySaveRequest); }
  • 73. 73 Sync with Application Bootstrap export default function* runAfterAuth(handler) { return function* (action){ const isAuthenticated = yield select(isAppAuthDone); if (!isAuthenticated) { yield take(APP_AUTH_SUCCESS); } yield call(handler, action) } }
  • 74. 74 Invest in Error Handling 1. Acton Error Naming Convention • like “*_ERROR” postfix in actions naming 2. Unified way to make requests, I/O 3. Logger and some UI to show error to the user
  • 75. 75 Error Handling export default function* rootSaga() { try { yield all([ watchAuth(), watchEntities() ]) } catch (e) { logger.error(e); yield put(errorCritical(e)); } }
  • 78. 78 Unit Testing Strategy 1. Start from covering top flows for example • must have watchAuth, watchCheckout • nice to have watchEntities 2. Cover reusable sagas like standartRequest, runAfterAuth
  • 82. 82 Summary 1. Inspired by Saga pattern, however it’s not exact implementation of Saga pattern 2. Provides constraints to handle side-effects in one place 3. Allows maintainable unit testing of side-effect (without mocking) 4. Saga works great for side-effects, but produces code smells if used for other tasks like routing, data massaging (aka reducers logic)
  • 84. 84 Future Reading ● Origins ○ Sagas - original paper ○ Confusion about Saga pattern ○ Clarifying the Saga pattern ○ Communicating Sequential Processes ● redux-saga ○ Saga ? Why not CSP ? ○ External Resources ● Other Domains ○ Applying Saga Pattern ○ Sagas ● Unit Testing ○ Mocking is a Code Smell
  • 88. 88 Side-Effects ● State/Assignments ● Read/Write Data ● Communicate Over Network ● Raise Exception ● DOM In computer science, a function or expression is said to have a side effect if, in addition to producing a value, it also modifies some state or has an observable interaction with calling functions or the outside world
  • 89. 89 Give Me a Label const label = await this.getLabel();
  • 90. 90 May Launch Missiles async function getLabel () { const val = Math.random(); if (val > 0.5){ await launchMissles(); return `foo foo ${val}` } return `blah blah ${val}`; }
  • 91. 91 Why should I care about side effects ? “Side effects are lies. Your function promises to do one thing, but it also does other hidden things...they are devious and damaging mistruths that often result in strange temporal couplings and order dependencies.” Clean Code, Robert Martin
  • 92. 92 Things to remember ● A program without side effects is useless ● Side effects are neither evil nor taboo ● The key is to ○ limit side effects ○ clearly identify them ○ avoid scattering them throughout the code.
  • 93. 93 Minuses ● issues with stacktrace ● more boilerplate code ● structuring sagas ● learning curve
  • 94. 94 Pluses ● side-effects isolated in one place ● maintainable code (unit testable) ● loosely coupled system
  • 96. 96 Basics Concepts 1. Separate Instructions from Execution 2. Use ES6 generator to define set of instructions 3. Use redux middleware to execute instructions 4. Execution works with `pull-future-actions` approach
  • 97. 97 Saga 1. Improve Loose Coupling (SR, Component and Actions) 2. Something on top of async/await, Observables 3. Maintainable Unit Testing (without mocks) 4. Makes important business flows explicitly defined in code 5. More explicit error handling techniques