技巧

节流(Throtting)

你可以通过在监听的 Saga 里调用一个 delay 函数,针对一系列发起的 action 进行节流。 举个例子,假设用户在文本框输入文字的时候,UI 触发了一个 INPUT_CHANGED action:

import { throttle } from 'redux-saga/effects'

function* handleInput(input) {
  // ...
}

function* watchInput() {
  yield throttle(500, 'INPUT_CHANGED', handleInput)
}

通过throttle,watchInput不会在500ms内启动一个新的handleInput任务,但在相同时间内,它仍然接受最新的INPUT_CHANGED 到底层的 buffer,所以它会忽略所有的 INPUT_CHANGED action。 这确保了 Saga 在 500ms 这段时间,最多接受一个 INPUT_CHANGED action,并且可以继续处理 trailing action。

防抖动(Debouncing)

为了对action队列进行防抖动,可以在被fork的任务里放置一个delay。

/**
 * @description 查询用户列表
 */
export function* fetchUsers() {
    yield delay(500)
    const {list}: PagesResult<User> = yield call(fetchUsersApi);
    yield put(setUsers(list));
}

function* watchFetchUsers() {
    let fetchUserTask: Task | undefined;
    while (true) {
        yield take(fetchUsersSagaAction)
        if (fetchUserTask) {
            yield cancel(fetchUserTask)
        }
        fetchUserTask = yield fork(fetchUsers)
    }
}

function* watchFetchUsers() {
    let fetchUserTask: Task | undefined;
    while (true) {
        yield take(fetchUsersSagaAction)
        if (fetchUserTask) {
            yield cancel(fetchUserTask)
        }
        fetchUserTask = yield fork(fetchUsers)
    }
}

export default function* userSaga() {
    yield watchFetchUsers();
}

在上面的示例中,fetchUsersApi在执行之前等待了500ms。如果在此期间,接收到的fetchUsersSagaAction,由于fetchUsersdelay阻塞,所以在执行自己的逻辑之前会被watchFetchUsers所取消。

例如,在 React 严格模式下,通过该方式可有效减少重复的请求。

上面的例子还可以使用redux-sagatakeLatest 重写:

最后更新于