使用 Saga Helpers
redux-saga
提供了一些 helper function,當指定的 action 被 dispatch 到 Store 時會產生 task。
helper function 建立在低階的 API 上。我們在進階部份會看到這些 function 可以被實現。
第一個 function takeEvery
是我們很熟悉的,它提供類似於 redux-thunk
的行為。
讓我們說明一些常見的 AJAX 範例。在每次按下 Fetch 按鈕時,我們 dispatch 一個 FETCH_REQUESTED
的 aciton。透過啟動這個 task,將從伺服器取得一些資料處理這個 action。
首先我們建立 task 將執行非同步的 action:
import { call, put } from 'redux-saga/effects'
export function* fetchData(action) {
try {
const data = yield call(Api.fetchUser, action.payload.url)
yield put({type: "FETCH_SUCCEEDED", data})
} catch (error) {
yield put({type: "FETCH_FAILED", error})
}
}
為了每次在得到 FETCH_REQUESTED
action 時,啟動上面的 task:
import { takeEvery } from 'redux-saga/effects'
function* watchFetchData() {
yield takeEvery('FETCH_REQUESTED', fetchData)
}
在以上的範例中,takeEvery
允許多個 fetchData
實例被同時啟動。在特定的時間,我們啟動一個新的 fetchData
task,儘管前面還有一個或多個 fetchData
task 還沒結束。
如果我們只想要取得最新被觸發請求的 response(例如:顯示最新版本的資料),我們可以使用 takeLatest
helper:
import { takeLatest } from 'redux-saga/effects'
function* watchFetchData() {
yield takeLatest('FETCH_REQUESTED', fetchData)
}
與 takeEvery
不同的是,takeLatest
在任何時候只允許一個 fetchData
task 執行,它將啟動最新的 task。如果先前提供的 task 還在執行,當其他的 fetchData
task 被啟動,先前的 task 會自動被取消。
如果你有多個 Saga 觀察不同的 action,你可以建立多個 watcher 和 fork
(我們之後將討論關於 fork
,現在它是一個 Effect 允許我們在背景啟動多個 Saga。現在,考慮一個 Effect 允許我們在背景中執行多個 saga)。
例如:
import { takeEvery } from 'redux-saga/effects'
// FETCH_USERS
function* fetchUsers(action) { ... }
// CREATE_USER
function* createUser(action) { ... }
// 在並行下使用它們
export default function* rootSaga() {
yield takeEvery('FETCH_USERS', fetchUsers)
yield takeEvery('CREATE_USER', createUser)
}