Saga 的概念有點像 Event Loop,使用 take helpers 觀測 Trigger Action(load) 是否被 Dispatch,進而透過 Generator Function 使用 Call Effect 執行 Async Requests,再用 Put Effect 去 Dispatch 不同階段的 Action(loading, loaded, failed...) 以讓 UI 物件呈現出不同變化。
The concept of saga is like event loop, take effect/helpers for watching action, call effect for handling async request and put effect for dispatching different stage of actions(loading, loaded, failed...). Unlike thunk get invoked on every actions, saga only run once at the start and process watching in the background. About saga and thunk, two of the most common differences are async task could be cancelled at any moment, and the structure of saga is easy for developer to test different stage of actions.
###Flow
Update specific article title of list:
UPDATE_TITLE actionupdateTitle task(take effect)updateTitleAPI async request(call effect)UPDATE_TITLE_SUCCESS, UPDATE_TITLE_FAILED(put effect)FETCH_LIST(fork effect)Thunk code will look like this:
const updateTitle = article => {
return async dispatch => {
dispatch({ type: UPDATE_TITLE });
try {
const res = await fetch(`url`, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: {
title: article.title
}
});
const json = await res.json();
dispatch({ type: UPDATE_TITLE_SUCCESS });
} catch(err) {
dispatch({ type: UPDATE_TITLE_FAILED });
}
}
}
In saga, it will be
// action.updateTitle -> saga.watchUpdateTitle -> saga.updateTitle -> action.updateTitleAPI
// action
const updateTitleAPI = fetch(...).then(res => res.json());
const updateTitle = article => ({ type: UPDATE_TITLE, article });
// saga
function* updateTitle() {
try {
yield call(updateTitleAPI, action.article.title);
yield put({ type: UPDATE_TITLE_SUCCESS });
yield fork(fetchArticles);
} catch(err) {
yield put({ type: UPDATE_TITLE_FAILED });
}
}
function* watchUpdateTitle() {
yield takeLatest(UPDATE_TITLE, updateTitle);
}
Ref: