redux-sagaからredux-observableへ書き換え
仕事でredux-observable
を使うことになったので、書き換えてみた備忘録。
ちなみにまだredux-observable
触って2日目の初心者なので多目にみてもらえると
Before
よくあるredux-saga
の処理。
reducer
とstore
の設定周りとか、詳細は省きます。
actions
import { createAction } from 'redux-actions';
export const findUser = createAction('findUser');
sagas
function * findUserHandler(payload) {
try {
yield put(showLoading());
const { data } = yield call(api.user.find, payload);
yield put(findUserSuccess(data));
} catch (error) {
yield put(findUserFail(error.response));
} finally {
yield put(hideLoading());
}
}
export default function * rootSaga() {
yield [
takeEvery(actions.findUser.toString(), findUserHandler)
]
);
厄介なのはshowLoading
アクションとhideLoading
アクションを非同期処理の処理の前後で呼ぶところです。
issueでもこんな質問が上がってましたが、そもそも解決策が高度過ぎて理解ができなくて解決できず・・・orz
ここに書いてあるような感じだとパラメータ固定で実用的でないし、、、。
ので、自分で書いてみることにしました。
After
試行錯誤の結果、ソースコードがこうなりました。
epic
export default function findUser(action$) {
return action$.ofType(actions.findUser.toString())
.map(action => action.payload)
.mergeMap(payload => Rx.Observable.of(
Rx.Observable.of(showLoading()),
Rx.Observable.fromPromise(api.user.find(payload))
.map(({ data }) => findUserSuccess(data))
.catch((error) => Rx.Observable.throw(error)),
Rx.Observable.of(hideLoading()),
)
)
.concatMap((action) => Rx.Observable.zip(action, (data) => data))
.catch((error) => Rx.Observable.of(findUserFail(error), hideLoading()))
}
-
map
でpayload
を取得。 -
mergeMap
で非同期に処理を行う(Rx.Observable.ofで3つのObservableを返す) -
concatMap
に3回Observable
が渡されるので、ひとつずつ順番に処理する。
よく考えたらshowLoading
の前にapi.user.find(payload)
が実行されちゃうから変な気がしてきた...
でもPromiseObservableで待ってくれてるぽい。。。うーむ orz
参考
Redux-Saga V.S. Redux-Observable
Process Manager dispatch multiple actions #62
おしまい。