gary-bendig-5x7PmmHanG4-unsplash.jpg

redux-sagaまとめ

 
0
このエントリーをはてなブックマークに追加
Kazuki Moriyama
Kazuki Moriyama (森山 和樹)

Effect creators

8. API Reference · Redux-Saga

take

指定されたパターンのアクションが発行されるまでこのtakeで止まる。

takeLatest

アクションを受けてsaga関数を発火する。
同じアクションでまだ実行中のプロセスがあれば殺す。

中身はforkなので処理をブロックしない。
以下で分かる通り無限にactionを待ち続けるところが他の多くのeffectと異なるところ。

const takeLatest = (patternOrChannel, saga, …args) => fork(function*() {
  let lastTask
  while (true) {
    const action = yield take(patternOrChannel)
    if (lastTask) {
      yield cancel(lastTask) // cancel is no-op if the task has already terminated
    }
    lastTask = yield fork(saga, ...args.concat(action))
  }
})

race

複数のeffectを受けて、どれかが終了したら他effectも中断する。
これを利用して非同期処理のキャンセルを実装できる。

import { take, call, race } from 'redux-saga/effects'
import fetchUsers from './path/to/fetchUsers'

function* fetchUsersSaga() {
  const [response, cancel] = yield race([
    call(fetchUsers),
    take(CANCEL_FETCH) // CANCEL_FETCHがdispatchされるとfetchUsersがキャンセルされる
  ])
}

all

複数のeffectを並列実行し、それらすべての完了を待つ。

call

渡された関数と引数を実行し、その場で待つ。

fork

callと同様に関数を実行するが、処理を待たない。
raceの中でforkは使用してはいけない。

// DO NOT DO THIS. The fork effect always win the race immediately.
yield race([
  fork(someSaga),
  take('SOME-ACTION'),
  somePromise,
])

delay

yield delay(mills)でmillsミリ秒待つ

sagaのforkモデル

非同期タスクをforkさせる方法として

  • Attached fork
  • Detached fork
    の2つがある。
    Effectをネストさせるとき親と子の関係が違ってくる。

Attached fork

  • forkメソッドを使用して作成する
  • 親はすべての子の完了を待つ
  • 一つの子がエラーを吐くと兄弟と親も殺す
  • 親がキャンセルされると子も全てキャンセルされる

Detached fork

  • spawnメソッドを使用して作成する
  • 親と子になんのつながりもない
  • 完了、エラー、キャンセルが親と子のいずれで起ころうともう片方になんの影響も及ぼさない

sagaレシピ

polling

必要なアクション

  1. polling start
  2. polling resultを流すアクション
  3. polling stop

必要なジェネレータ関数

  1. 無限にstartを監視し続けるwatcher function
  2. 無限にpollingを続けるworker function

pollingの流れ

  1. startを検知したwatcherがtake(stop)とworkerをraceで走らせる
  2. workerは無限にpollingし、結果を受け取ると通知する
  3. stopが発行されるとraceが終了しpollingが終了する
import { race, take, call } from 'redux-saga/effects'

/* Worker Function */
function* pollTask() {
    while (true) {
        try {
            // Fetching posts at regular interval 4 seconds.
            const posts = yield call(httpGet, 'posts');
            yield put({
                type: 'ON_POST_FETCH_SUCCESS',
                posts: posts
            });
            yield call(delay, 4000);
        } catch (err) {
            yield put({
                type: 'ON_POST_FETCH_ERROR',
                message: err.message
            });
            // Once the polling has encountered an error,
            // it should be stopped immediately
            yield put({ type: 'STOP_WATCHER_TASK', err });
        }
    }
}

/* Watcher Function */
function* pollTaskWatcher() {
    while (true) {
        yield take('START_WATCHER_TASK')
        yield race( [call(pollTask), take('STOP_WATCHER_TASK')] )
    }
}

Polling with Redux saga - Noteworthy - The Journal Blog

info-outline

お知らせ

K.DEVは株式会社KDOTにより運営されています。記事の内容や会社でのITに関わる一般的なご相談に専門の社員がお答えしております。ぜひお気軽にご連絡ください。