Help us understand the problem. What is going on with this article?

連続した非同期通信を行う際のローディング管理が、redux-saga を使ったら便利だった話

More than 1 year has passed since last update.

前書き

この記事は redux-saga の使い方はあまり記述していません。
あくまで使ってみたら便利だった体験談を備忘録がわりに書き留めたものです。

連続した非同期通信ケース

そもそも連続した非同期通信が走る状況ってどんなときってことなんですが
下のケースが例として挙げられます。

  • ニュース一覧リストをレイジーロードする時
  • 料金取得APIなど、フロント側のInput要素のChangeイベントごとにAPIを叩く時
  • 商品リストの「次へ」ボタンをユーザーが連打する時

これらのAPI通信が走っている際、画面にローディングを付けたいと思うかもしれません。
その際、ローディングを終えるタイミングは連続したAPIコールの最後の処理が終わった時ですよね。

簡単に今まで書いていた処理を記述してみました。

actionCreator.js
// セッションの宣言
const session = new Date().getTime()

// ローディング開始アクションにセッションを渡す
  dispatch<LoadStart>({
    type: ActionTypes.LoadStart,
    payload: { session }
  })

  try {
  // 非同期通信開始
    const resp = await getHogeApiResponse(requestParam)

  // 通信成功時、payloadにセッション情報も含める
    dispatch<LoadEnd>({
      type: ActionTypes.LoadEnd,
      payload: { data: resp, session }
    })
  } catch (e) {
  // 通信失敗時、payloadにセッション情報も含める
    dispatch<LoadEnd>({
      type: ActionTypes.LoadEnd,
      payload: { session }
    })
  }
  • セッションを宣言し、非同期通信をする直前でステートにセッションを登録
  • APIをコールし、通信成功・失敗に関わらず再度セッションを渡す
  • ステートのセッションを比較し、セッションが異なれば、他にAPIコールが行われているためローディングを続行
  • ステートのセッションを比較し、同一だったらローディング終了

という流れです。

この処理を非同期通信部分に1個1個書いていく必要があるため、手間に感じていました。

redux-saga を使った場合

saga.js
function* fetchHoge(action) {
  try {
  // 非同期通信開始、callの第一引数でAPI通信関数、第二引数で通信処理の引数を指定
    const resp = yield call(getHogeApiResponse, {
      requestParam: action.payload
    })
// 通信成功時
    yield put<FetchHogeSucceeded>({
      type: ActionTypes.FetchHogeSucceeded,
      payload: resp
    })
  } catch (e) {
  // 通信失敗時
    yield put<FetchHogeFailed>({
      type: ActionTypes.FetchHogeFailed
    })
  }
}

export function* sagas() {
// ActionTypes.FetchHogeRequestedを監視
// このアクションが呼ばれたらfetchHogeを起動する。
  yield takeLatest(ActionTypes.FetchHogeRequested, fetchHoge)
}

redux-saga本来の書き方が特徴的であるため、前述したものと比べて冗長に見えますが
セッションに当たる部分を担っているのは下のほうに記述してある takeLatest 指定のみです。

takeLatestの動作

もしレスポンス待ちの状態で USER_FETCH_REQUESTED を受け取った場合、
待ち状態のリクエストはキャンセルされて最後の1つだけが実行されます。

公式だとこうなっていますね。
連打される可能性のある非同期通信処理が10個あったとしても10回takeLatest指定してあげれば良いわけです。
とても楽チン。

逆にすべて並列で処理したい場合はtakeEveryが使えます。

まとめ

今回のことでredux-sagaが最高! と断言するわけではありません。
しっかりかけますが、記述も独特で若干冗長になりやすいです。

ただ、非同期通信処理をStore内で切り分けられるので設計を整理しやすく、好印象でした。

個人的には
簡単な非同期通信処理のみ扱う際は redux-thunk
しっかりと非同期通信処理を管理したい場合は redux-saga
という印象です。

また次の機会にも使っていこうと思います。

ここまでお読みいただきありがとうございました。

EndouT6
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした