SlideShare a Scribd company logo
1 of 111
Download to read offline
Why Redux-Observable?
JSDC
2017/11/04
2
3
通常我們如何在 Redux 處理理
非同步問題?
5
Redux-thunk
6
Redux-thunk
redux 專案⼤大多使⽤用 redux-thunk 處理理非同步問題
為什什麼不繼續使⽤用
Redux-thunk
7
?
我們來來想想...
實務上我們可能會遇到哪些問題?
8
PM 跟你說:網站要做 搜尋 功能
9
‣ 顯⽰示搜尋結果
‣ 記錄關鍵字 History
如果使⽤用 redux-thunk
我們來來看程式碼可能會怎麼寫...
10
?
搜尋功能
你可能會這樣寫...
11
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
搜尋功能
搜尋關鍵字必須有值,
才執⾏行行 request
12
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
搜尋功能
回傳搜尋資料之前,
顯⽰示 Loading 動畫
13
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST });
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
搜尋功能
GET API,取得搜尋資料
14
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
搜尋功能
觸發另外⼀一個 action
顯⽰示搜尋結果
15
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
搜尋功能
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
變更更網址
16
搜尋功能
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
傳入關鍵字,記錄 History
17
如何在 Redux-thunk
取消 request?
18
如何在 Redux-thunk
取消 request?
19
20
搜尋功能
宣告 controller 變數
21
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
搜尋功能
新增 controller
提供取消 request 的⽅方法
22
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?keyword=${keyword}&lim
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
搜尋功能
將舊的 request 取消,
執⾏行行新的 request
23
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?keyword=${keyword}&lim
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
搜尋功能
使⽤用 redux-thunk…
24
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?keyword=${keyword}&limit=20`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
25
有沒有更更快速⼜又簡單的⽅方法?
幫我們解決這些常⾒見見的非同步問題
26
redux-thunk redux-observable
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
export const searchEpic = action$ !=>
action$
.ofType(SEARCH_REQUEST)
.filter(action !=> action.payload)
.switchMap(getSearchResult)
.mergeMap(res !=>
Observable.of(
receiveSearchResult(res.data),
push(`/search/${res.keyword}`),
addSearchHistory(res.keyword)
)
);
27
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
export const searchEpic = action$ !=>
action$
.ofType(SEARCH_REQUEST)
.filter(action !=> action.payload)
.switchMap(getSearchResult)
.mergeMap(res !=>
Observable.of(
receiveSearchResult(res.data),
push(`/search/${res.keyword}`),
addSearchHistory(res.keyword)
)
);
25⾏行行程式碼 12⾏行行程式碼
程式碼 少了了 1/2
redux-observable
⼤大約
28
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
export const searchEpic = action$ !=>
action$
.ofType(SEARCH_REQUEST)
.filter(action !=> action.payload)
.switchMap(getSearchResult)
.mergeMap(res !=>
Observable.of(
receiveSearchResult(res.data),
push(`/search/${res.keyword}`),
addSearchHistory(res.keyword)
)
);
有 if 判斷 沒有 if 判斷
程式碼 容易易閱讀
redux-observable
比較
29
let controller;
export const search = keyword !=> dispatch !=> {
if (!keyword) {
return;
}
dispatch({ type: SEARCH_REQUEST});
if (controller) {
controller.abort();
}
controller = new AbortController();
return fetch(`/search?k=${keyword}`, {
signal: controller.signal,
}).then(res !=> {
dispatch(receiveSearchResult(res));
dispatch(push(`/search/${keyword}`));
dispatch(addKeywordHistory(keyword));
controller = undefined;
});
};
export const searchEpic = action$ !=>
action$
.ofType(SEARCH_REQUEST)
.filter(action !=> action.payload)
.switchMap(getSearchResult)
.mergeMap(res !=>
Observable.of(
receiveSearchResult(res.data),
push(`/search/${res.keyword}`),
addSearchHistory(res.keyword)
)
);
只⽀支援 firefox 57 版 只有 IE 10 以下不⽀支援
有效率的完成功能
redux-observable
30
好像還不錯?!
Redux-Observable
Redux-Observable
What’s
Redux-Observable?
RxJS 5-based middleware for Redux
32
33
Store
dispatch
Reducer
Action
Middleware
Component
State
34
Store
dispatch
Reducer
Action
Middleware
Component
State
35
Store
dispatch
Reducer
Action
Middleware
Component
State
36
Store
dispatch
Reducer
Action
Middleware
Component
State
37
Store
dispatch
epic epic epic epicepic
redux-observable
Reducer
Action
State
38
Store
dispatch
epic epic epic epicepic
redux-observable
Reducer
Action
State
39
Store
dispatch
epic epic epic epicepic
redux-observable
Reducer
Action
State
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
Epic
40
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
Epic
41
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
Epic
42
43
epic epic epic epicepic
epic epic epic epicepic
rootEpic
44
rootEpic.js
45
import { combineEpics } from 'redux-observable';
import { openToastEpic } from './toastStatus.js';
import { checkEmailEpic } from './emailCheckStatus.js';
import { searchEpic } from './search.js';
import { getArticlesEpic } from './articles.js';
export default combineEpics(
openToastEpic,
checkEmailEpic,
searchEpic,
getArticlesEpic
);
index.js
46
…
const store = createStore(
reducer,
applyMiddleware(createEpicMiddleware(rootEpics))
);
…
Store
Middleware
Reducer
index.js
47
…
const store = createStore(
reducer,
applyMiddleware(createEpicMiddleware(rootEpics))
);
…
Store
Middleware
Reducer
index.js
48
…
const store = createStore(
reducer,
applyMiddleware(createEpicMiddleware(rootEpics))
);
…
Store
Middleware
Reducer
49
50
訊息通知
51
按下確定按鈕
52
open toast
53
訊息通知
按下按鈕
觸發 action creator
54
<button onClick={openToast}>確定#</button>
訊息通知
建立 action creator 和 epic
55
export const openToast = () !=> ({
type: OPEN_TOAST,
});
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
訊息通知
傳入 action observable
56
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
訊息通知
過濾出對應的 action type
57
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
訊息通知
delay 3 秒
58
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
訊息通知
觸發關閉 Toast 的 action
59
export const openToastEpic = action$ !=> {
return action$
.ofType(OPEN_TOAST)
.delay(3000)
.mapTo({ type: CLOSE_TOAST });
};
訊息通知
到 reducer、更更新 state
改變 store
60
export default function toastStatus(state = false, action) {
switch (action.type) {
case OPEN_TOAST:
return true;
case CLOSE_TOAST:
return false;
default:
return state;
}
}
訊息通知
到 reducer、更更新 state
改變 store
61
export default function toastStatus(state = false, action) {
switch (action.type) {
case OPEN_TOAST:
return true;
case CLOSE_TOAST:
return false;
default:
return state;
}
}
訊息通知
UI 發⽣生改變
62
<div className={classNames('toast', { show })}>
<p>儲存成功!#</p>
#</div>
Redux-Observable
use case
64
E-mail 即時驗證 載入更更多⽂文章
Redux-Observable use case
65
E-mail 即時驗證
66
67
68
取消舊的 request,執⾏行行新的 request
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
過濾出對應的 action type
69
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
觸發後,靜置500毫秒
70
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
觸發後,靜置500毫秒才做驗證
71
通常⽤用在輸入框
靜置⼀一段時間才觸發
debounceTime
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
接收最新的 request,
舊的 request 都取消
72
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
取最新的 request,
舊的 request 都取消
73
取消舊的 request,執⾏行行新的 request
switchMap
情境1: 表單即時驗證
情境2: Autocomplete 的輸入框
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
獲取 Email 狀狀態
74
75
ㄈ
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
Email 格式正確才發 request
76
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
觸發後,靜置500毫秒才做驗證
77
快速輕鬆的完成功能
不需要會 RxJS,就可以使⽤用 operator
78
載入更更多⽂文章
79
過濾出對應的 action type
80
export const getArticlesEpic = action$ !=> {
return action$
.ofType(GET_ARTICLES)
.exhaustMap(getArticlesAPI)
.map(receiveArticles);
};
載入更更多⽂文章
取原本送出的 request,
新的 request 都取消
81
export const getArticlesEpic = action$ !=> {
return action$
.ofType(GET_ARTICLES)
.exhaustMap(getArticlesAPI)
.map(receiveArticles);
};
載入更更多⽂文章
82
無限滾動⽂文章
83
無限滾動⽂文章
export const getArticlesEpic = action$ !=> {
return action$
.ofType(GET_ARTICLES)
.exhaustMap(getArticlesAPI)
.map(receiveArticles);
};
取原本送出的 request,
新的 request 都取消
84
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
取最新的 request,
舊的 request 都取消
85
取原本送出的 request,新的 request 都取消
exhaustMap
情境1: 看更更多⽂文章
情境2: 上傳檔案
export const getArticlesEpic = actions !=> {
return actions
.ofType(GET_ARTICLES)
.throttleTime(100)
.exhaustMap(getArticlesAPI)
.map(receiveArticles);
};
無限滾動⽂文章
throttle 100 毫秒
才送 request
86
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
觸發後,靜置500毫秒才做驗證
87
通常⽤用在連續性⾏行行為
throttleTime
情境1: 滾動事件
情境2: 拖拉事件
避免⾼高頻率觸發
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
觸發後,靜置500毫秒才做驗證
88
重⽤用性與可讀性提昇
組合使⽤用 operator
Email 即時驗證
export const checkEmailEpic = actions !=> {
return actions
.ofType(CHECK_EMAIL)
.debounceTime(500)
.filter(validateEmail)
.switchMap(checkEmailIsUnique)
.map(receiveEmailStatus);
};
觸發後,靜置500毫秒才做驗證
89
優雅的解決非同步問題
簡單使⽤用 operator
你不需要會 RxJS,
就可以直接使⽤用 Redux-Observable !
90
91
Compare with
other middleware ?
93
13 Jul 2015
redux-thunk redux-saga
3 Dec 2015
redux-observable
21 Apr 2016
redux-cycle
3 Dec 2016
2017/10/23
Redux middlewares
redux-thunk redux-observable
94
export const openPopup = () !=> dispatch !=> {
dispatch({
type: OPEN_POPUP,
});
setTimeout(() !=> {
dispatch({
type: CLOSE_POPUP,
});
}, 3000);
};
export const openPopupEpic = action$ !=> {
return action$
.ofType(OPEN_POPUP)
.delay(3000)
.mapTo({ type: CLOSE_POPUP });
};
redux-thunk
•容易易上⼿手
•程式碼冗長
•不易易閱讀
•難以維護
95
export const openPopup = () !=> dispatch !=> {
dispatch({
type: OPEN_POPUP,
});
setTimeout(() !=> {
dispatch({
type: CLOSE_POPUP,
});
}, 3000);
};
redux-saga redux-observable
96
export function* openPopupAsync () {
yield call(delay, 3000)
yield put({ type: 'CLOSE_POPUP' })
}
export function* watchOpenPopupAsync () {
yield takeEvery('OPEN_POPUP', openPopupAsync)
}
export const openPopupEpic = action$ !=> {
return action$
.ofType(OPEN_POPUP)
.delay(3000)
.mapTo({ type: CLOSE_POPUP });
};
redux-saga
•技術不能轉移
•依賴 syntax (Generator)
97
export function* openPopupAsync () {
yield call(delay, 3000)
yield put({ type: 'CLOSE_POPUP' })
}
export function* watchOpenPopupAsync () {
yield takeEvery('OPEN_POPUP', openPopupAsync)
}
•可以處理理較複雜的非同步問題
•星星數較多,使⽤用社群較⼤大
redux-cycles redux-observable
98
export const openPopupEpic = action$ !=> {
return action$
.ofType(OPEN_POPUP)
.delay(3000)
.mapTo({ type: CLOSE_POPUP });
};
function openPopup (sources) {
const openPopup$ = sources.ACTION
.filter(action !=> action.type &&=== OPEN_POPUP)
.delay(3000)
.mapTo({ type: CLOSE_POPUP });
return {
ACTION: openPopup$
}
}
redux-cycles redux-observable
99
function fetchUserData(sources) {
const request$ = sources.ACTION
.filter(action !=> action.type &&=== FETCH_USER)
.map(action !=> ({
url: `${API_URL}users/`,
category: 'users',
}));
const action$ = sources.HTTP
.select('users')
.flatten()
.map(fetchUserFulfilled);
return {
ACTION: action$,
HTTP: request$,
};
}
const fetchUserDataEpic = action$ !=>
action$
.ofType(FETCH_USER)
.mergeMap(action !=>
ajax.getJSON(`${API_URL}users/`)
.map(fetchUserFulfilled)
);
redux-cycle
•社群⼈人數較少
•過度封裝?
100
function fetchUserData(sources) {
const request$ = sources.ACTION
.filter(action !=> action.type &&=== FETCH_USER)
.map(action !=> ({
url: `${API_URL}users/`,
category: 'users',
}));
const action$ = sources.HTTP
.select('users')
.flatten()
.map(fetchUserFulfilled);
return {
ACTION: action$,
HTTP: request$,
};
}
•可以處理理較複雜的
非同步問題
101
redux-thunk redux-saga redux-cycle redux-observable
程式碼簡潔
處理複雜的⾮同步情境
技術可轉移
Why Redux-Observable?
102
redux-thunk redux-saga redux-cycle redux-observable
程式碼簡潔
處理複雜的⾮同步情境
技術可轉移
Why Redux-Observable?
(你應該學習 Observable 的原因)
103
技術可轉移
RxJava
RxPHP
將成為 ECMAScript 標準
Stage1
前端框架都有 Observable
Redux-Observable
vue-rx
Angular2 之後RxSwift
Why Redux-Observable?
104
‣ 程式碼更更簡潔
‣ 可讀性更更⾼高
‣ 容易易寫測試
‣ 更更快速完成功能
Why Redux-Observable?
105
106
107
108
Reference
‣ https://redux-observable.js.org/
‣ https://github.com/redux-observable/redux-observable
‣ http://reactivex.io/languages.html
‣ https://github.com/reactjs/redux/issues/1461#issuecomment-190165193
‣ https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
‣ https://twitter.com/dan_abramov/status/816244945015160832
109
Image Credit
‣ http://oreilly-generator.com/
‣ http://renzhou.tw/yinwubrother-textmaker/
‣ https://www.flaticon.com/packs/emoji-6
‣ https://www.flaticon.com/packs/design-35
110
Thank you :D

More Related Content

What's hot

Asynchronní programování
Asynchronní programováníAsynchronní programování
Asynchronní programováníPeckaDesign.cz
 
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerNode.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerIslam Sharabash
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)xSawyer
 
Correcting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NETCorrecting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NETBrandon Minnick, MBA
 
Correcting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await MistakesCorrecting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await MistakesBrandon Minnick, MBA
 
Angular server-side communication
Angular server-side communicationAngular server-side communication
Angular server-side communicationAlexe Bogdan
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the mastersAra Pehlivanian
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queueAlex Eftimie
 
Debugging JavaScript with Chrome
Debugging JavaScript with ChromeDebugging JavaScript with Chrome
Debugging JavaScript with ChromeIgor Zalutsky
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and httpAlexe Bogdan
 
Automation in angular js
Automation in angular jsAutomation in angular js
Automation in angular jsMarcin Wosinek
 
Implicit and Explicit waits in Selenium WebDriwer, how to.
Implicit and Explicit waits in Selenium WebDriwer, how to.Implicit and Explicit waits in Selenium WebDriwer, how to.
Implicit and Explicit waits in Selenium WebDriwer, how to.Yaroslav Pernerovsky
 
Any event intro
Any event introAny event intro
Any event introqiang
 
Mirage For Beginners
Mirage For BeginnersMirage For Beginners
Mirage For BeginnersWilson Su
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous Shmuel Fomberg
 
Introduction to Service Workers | Matteo Manchi
Introduction to Service Workers | Matteo ManchiIntroduction to Service Workers | Matteo Manchi
Introduction to Service Workers | Matteo ManchiCodemotion
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureFDConf
 

What's hot (20)

Asynchronní programování
Asynchronní programováníAsynchronní programování
Asynchronní programování
 
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerNode.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
Correcting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NETCorrecting Common Async/Await Mistakes in .NET
Correcting Common Async/Await Mistakes in .NET
 
Correcting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await MistakesCorrecting Common .NET Async/Await Mistakes
Correcting Common .NET Async/Await Mistakes
 
Angular server-side communication
Angular server-side communicationAngular server-side communication
Angular server-side communication
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queue
 
Debugging JavaScript with Chrome
Debugging JavaScript with ChromeDebugging JavaScript with Chrome
Debugging JavaScript with Chrome
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
 
Automation in angular js
Automation in angular jsAutomation in angular js
Automation in angular js
 
WebDriver Waits
WebDriver WaitsWebDriver Waits
WebDriver Waits
 
Implicit and Explicit waits in Selenium WebDriwer, how to.
Implicit and Explicit waits in Selenium WebDriwer, how to.Implicit and Explicit waits in Selenium WebDriwer, how to.
Implicit and Explicit waits in Selenium WebDriwer, how to.
 
Any event intro
Any event introAny event intro
Any event intro
 
Automation puzzlers
Automation puzzlersAutomation puzzlers
Automation puzzlers
 
Practical Celery
Practical CeleryPractical Celery
Practical Celery
 
Mirage For Beginners
Mirage For BeginnersMirage For Beginners
Mirage For Beginners
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
 
Introduction to Service Workers | Matteo Manchi
Introduction to Service Workers | Matteo ManchiIntroduction to Service Workers | Matteo Manchi
Introduction to Service Workers | Matteo Manchi
 
Scalable Angular 2 Application Architecture
Scalable Angular 2 Application ArchitectureScalable Angular 2 Application Architecture
Scalable Angular 2 Application Architecture
 

Similar to Why Redux-Observable?

Prescribing RX Responsibly
Prescribing RX ResponsiblyPrescribing RX Responsibly
Prescribing RX ResponsiblyNareg Khoshafian
 
An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...
An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...
An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...GreeceJS
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Astrails
 
Bulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & CouchbaseBulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & CouchbaseAlex Derkach
 
Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCLFastly
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015Michiel Borkent
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best PracticesYekmer Simsek
 
Chromium Embedded Framework + Go at Brooklyn JS
Chromium Embedded Framework + Go at Brooklyn JSChromium Embedded Framework + Go at Brooklyn JS
Chromium Embedded Framework + Go at Brooklyn JSquirkey
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react applicationGreg Bergé
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises Marc Morera
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js frameworkBen Lin
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJSKyung Yeol Kim
 
[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data productIgor Lozynskyi
 
Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationBartosz Konieczny
 
Reactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz KhambatiReactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz KhambatiAziz Khambati
 

Similar to Why Redux-Observable? (20)

Side effects-con-redux
Side effects-con-reduxSide effects-con-redux
Side effects-con-redux
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
Prescribing RX Responsibly
Prescribing RX ResponsiblyPrescribing RX Responsibly
Prescribing RX Responsibly
 
An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...
An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...
An Emoji Introduction to React Native (Panagiotis Vourtsis, Senior Front End ...
 
Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.Migrating from Flux to Redux. Why and how.
Migrating from Flux to Redux. Why and how.
 
Bulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & CouchbaseBulding a reactive game engine with Spring 5 & Couchbase
Bulding a reactive game engine with Spring 5 & Couchbase
 
Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
 
Solving anything in VCL
Solving anything in VCLSolving anything in VCL
Solving anything in VCL
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Chromium Embedded Framework + Go at Brooklyn JS
Chromium Embedded Framework + Go at Brooklyn JSChromium Embedded Framework + Go at Brooklyn JS
Chromium Embedded Framework + Go at Brooklyn JS
 
Recompacting your react application
Recompacting your react applicationRecompacting your react application
Recompacting your react application
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 
[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product[JEEConf-2017] RxJava as a key component in mature Big Data product
[JEEConf-2017] RxJava as a key component in mature Big Data product
 
Headless Js Testing
Headless Js TestingHeadless Js Testing
Headless Js Testing
 
Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customization
 
Reactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz KhambatiReactive Programming - ReactFoo 2020 - Aziz Khambati
Reactive Programming - ReactFoo 2020 - Aziz Khambati
 

More from Anna Su

Clean Architecture
Clean ArchitectureClean Architecture
Clean ArchitectureAnna Su
 
2017 台灣成長駭客年會 與會心得分享
2017 台灣成長駭客年會 與會心得分享2017 台灣成長駭客年會 與會心得分享
2017 台灣成長駭客年會 與會心得分享Anna Su
 
PWA 應用與價值
PWA 應用與價值PWA 應用與價值
PWA 應用與價值Anna Su
 
初探 DevOps 的世界
初探 DevOps 的世界初探 DevOps 的世界
初探 DevOps 的世界Anna Su
 
NASA hackathon - Sea More
NASA hackathon - Sea MoreNASA hackathon - Sea More
NASA hackathon - Sea MoreAnna Su
 
用 Javascript 實現你的想像
用 Javascript 實現你的想像用 Javascript 實現你的想像
用 Javascript 實現你的想像Anna Su
 
PWA 應用 - 實現網站離線瀏覽
PWA 應用 - 實現網站離線瀏覽PWA 應用 - 實現網站離線瀏覽
PWA 應用 - 實現網站離線瀏覽Anna Su
 
網站建置流程
網站建置流程網站建置流程
網站建置流程Anna Su
 
網站建置初探
網站建置初探網站建置初探
網站建置初探Anna Su
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service WorkerAnna Su
 
2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事
2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事
2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事Anna Su
 
從一個超簡單範例開始學習 Canvas
從一個超簡單範例開始學習 Canvas從一個超簡單範例開始學習 Canvas
從一個超簡單範例開始學習 CanvasAnna Su
 
Rucksack 裝滿神奇 css 的後背包
Rucksack 裝滿神奇 css 的後背包Rucksack 裝滿神奇 css 的後背包
Rucksack 裝滿神奇 css 的後背包Anna Su
 
CSS modules 簡單玩
CSS modules 簡單玩CSS modules 簡單玩
CSS modules 簡單玩Anna Su
 
Trello - 規劃工作與生活的管理工具
Trello - 規劃工作與生活的管理工具Trello - 規劃工作與生活的管理工具
Trello - 規劃工作與生活的管理工具Anna Su
 
webpack 入門
webpack 入門webpack 入門
webpack 入門Anna Su
 
入門Gulp - 前端自動化開發工具
入門Gulp - 前端自動化開發工具入門Gulp - 前端自動化開發工具
入門Gulp - 前端自動化開發工具Anna Su
 
幸福快樂的完美結局
幸福快樂的完美結局幸福快樂的完美結局
幸福快樂的完美結局Anna Su
 
偷呷步的網站快速入門
偷呷步的網站快速入門偷呷步的網站快速入門
偷呷步的網站快速入門Anna Su
 
調配網站的明星花露水
調配網站的明星花露水調配網站的明星花露水
調配網站的明星花露水Anna Su
 

More from Anna Su (20)

Clean Architecture
Clean ArchitectureClean Architecture
Clean Architecture
 
2017 台灣成長駭客年會 與會心得分享
2017 台灣成長駭客年會 與會心得分享2017 台灣成長駭客年會 與會心得分享
2017 台灣成長駭客年會 與會心得分享
 
PWA 應用與價值
PWA 應用與價值PWA 應用與價值
PWA 應用與價值
 
初探 DevOps 的世界
初探 DevOps 的世界初探 DevOps 的世界
初探 DevOps 的世界
 
NASA hackathon - Sea More
NASA hackathon - Sea MoreNASA hackathon - Sea More
NASA hackathon - Sea More
 
用 Javascript 實現你的想像
用 Javascript 實現你的想像用 Javascript 實現你的想像
用 Javascript 實現你的想像
 
PWA 應用 - 實現網站離線瀏覽
PWA 應用 - 實現網站離線瀏覽PWA 應用 - 實現網站離線瀏覽
PWA 應用 - 實現網站離線瀏覽
 
網站建置流程
網站建置流程網站建置流程
網站建置流程
 
網站建置初探
網站建置初探網站建置初探
網站建置初探
 
PWA 與 Service Worker
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service Worker
 
2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事
2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事
2016 PIXNET HACKATHON Lightning talk - 做網站不是只有一個人的事
 
從一個超簡單範例開始學習 Canvas
從一個超簡單範例開始學習 Canvas從一個超簡單範例開始學習 Canvas
從一個超簡單範例開始學習 Canvas
 
Rucksack 裝滿神奇 css 的後背包
Rucksack 裝滿神奇 css 的後背包Rucksack 裝滿神奇 css 的後背包
Rucksack 裝滿神奇 css 的後背包
 
CSS modules 簡單玩
CSS modules 簡單玩CSS modules 簡單玩
CSS modules 簡單玩
 
Trello - 規劃工作與生活的管理工具
Trello - 規劃工作與生活的管理工具Trello - 規劃工作與生活的管理工具
Trello - 規劃工作與生活的管理工具
 
webpack 入門
webpack 入門webpack 入門
webpack 入門
 
入門Gulp - 前端自動化開發工具
入門Gulp - 前端自動化開發工具入門Gulp - 前端自動化開發工具
入門Gulp - 前端自動化開發工具
 
幸福快樂的完美結局
幸福快樂的完美結局幸福快樂的完美結局
幸福快樂的完美結局
 
偷呷步的網站快速入門
偷呷步的網站快速入門偷呷步的網站快速入門
偷呷步的網站快速入門
 
調配網站的明星花露水
調配網站的明星花露水調配網站的明星花露水
調配網站的明星花露水
 

Recently uploaded

Correctly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleCorrectly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleAlluxio, Inc.
 
Electronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdfElectronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdfme23b1001
 
Past, Present and Future of Generative AI
Past, Present and Future of Generative AIPast, Present and Future of Generative AI
Past, Present and Future of Generative AIabhishek36461
 
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfCCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfAsst.prof M.Gokilavani
 
Application of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptxApplication of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptx959SahilShah
 
Why does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsync
Why does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsyncWhy does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsync
Why does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsyncssuser2ae721
 
Churning of Butter, Factors affecting .
Churning of Butter, Factors affecting  .Churning of Butter, Factors affecting  .
Churning of Butter, Factors affecting .Satyam Kumar
 
What are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptxWhat are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptxwendy cai
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptSAURABHKUMAR892774
 
Call Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile serviceCall Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile servicerehmti665
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catcherssdickerson1
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024hassan khalil
 
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort serviceGurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort servicejennyeacort
 
INFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETE
INFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETEINFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETE
INFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETEroselinkalist12
 
IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024Mark Billinghurst
 

Recently uploaded (20)

Correctly Loading Incremental Data at Scale
Correctly Loading Incremental Data at ScaleCorrectly Loading Incremental Data at Scale
Correctly Loading Incremental Data at Scale
 
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCRCall Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
Call Us -/9953056974- Call Girls In Vikaspuri-/- Delhi NCR
 
Electronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdfElectronically Controlled suspensions system .pdf
Electronically Controlled suspensions system .pdf
 
Past, Present and Future of Generative AI
Past, Present and Future of Generative AIPast, Present and Future of Generative AI
Past, Present and Future of Generative AI
 
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdfCCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
CCS355 Neural Network & Deep Learning Unit II Notes with Question bank .pdf
 
Application of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptxApplication of Residue Theorem to evaluate real integrations.pptx
Application of Residue Theorem to evaluate real integrations.pptx
 
Why does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsync
Why does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsyncWhy does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsync
Why does (not) Kafka need fsync: Eliminating tail latency spikes caused by fsync
 
Churning of Butter, Factors affecting .
Churning of Butter, Factors affecting  .Churning of Butter, Factors affecting  .
Churning of Butter, Factors affecting .
 
What are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptxWhat are the advantages and disadvantages of membrane structures.pptx
What are the advantages and disadvantages of membrane structures.pptx
 
Arduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.pptArduino_CSE ece ppt for working and principal of arduino.ppt
Arduino_CSE ece ppt for working and principal of arduino.ppt
 
Call Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile serviceCall Girls Delhi {Jodhpur} 9711199012 high profile service
Call Girls Delhi {Jodhpur} 9711199012 high profile service
 
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTAC® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
 
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Serviceyoung call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
young call girls in Rajiv Chowk🔝 9953056974 🔝 Delhi escort Service
 
🔝9953056974🔝!!-YOUNG call girls in Rajendra Nagar Escort rvice Shot 2000 nigh...
🔝9953056974🔝!!-YOUNG call girls in Rajendra Nagar Escort rvice Shot 2000 nigh...🔝9953056974🔝!!-YOUNG call girls in Rajendra Nagar Escort rvice Shot 2000 nigh...
🔝9953056974🔝!!-YOUNG call girls in Rajendra Nagar Escort rvice Shot 2000 nigh...
 
Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024Architect Hassan Khalil Portfolio for 2024
Architect Hassan Khalil Portfolio for 2024
 
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort serviceGurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
Gurgaon ✡️9711147426✨Call In girls Gurgaon Sector 51 escort service
 
INFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETE
INFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETEINFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETE
INFLUENCE OF NANOSILICA ON THE PROPERTIES OF CONCRETE
 
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptxExploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
Exploring_Network_Security_with_JA3_by_Rakesh Seal.pptx
 
IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024IVE Industry Focused Event - Defence Sector 2024
IVE Industry Focused Event - Defence Sector 2024
 
POWER SYSTEMS-1 Complete notes examples
POWER SYSTEMS-1 Complete notes  examplesPOWER SYSTEMS-1 Complete notes  examples
POWER SYSTEMS-1 Complete notes examples
 

Why Redux-Observable?