Skip to content

redux-saga 指令

redux-saga 是一个用于管理 Redux 应用中副作用(如异步操作、API 请求等)的中间件。它使用 ES6 的 Generator 函数来编写易于测试和维护的异步逻辑。redux-saga 提供了一组指令(effects),这些指令可以让你以声明式的方式处理各种副作用。

redux-saga 的主要指令

以下是 redux-saga 中常用的一些指令(effects)及其用途:

1. call

用于调用函数或 Promise,不会自动 dispatch action。

javascript
import { call } from "redux-saga/effects";

function* fetchUser(action) {
  const user = yield call(Api.fetchUser, action.payload.userId);
  // ...
}

2. put

用于 dispatch action 到 Redux store。

javascript
import { put } from "redux-saga/effects";

function* fetchUser(action) {
  try {
    const user = yield call(Api.fetchUser, action.payload.userId);
    yield put({ type: "USER_FETCH_SUCCEEDED", user });
  } catch (error) {
    yield put({ type: "USER_FETCH_FAILED", error });
  }
}

3. take

等待指定类型的 action 被 dispatch。

javascript
import { take } from "redux-saga/effects";

function* watchFetchUser() {
  while (true) {
    const action = yield take("FETCH_USER");
    yield call(fetchUser, action);
  }
}

4. fork

用于启动一个新的 saga 任务,而不阻塞当前 saga 的执行。类似于并发执行。

javascript
import { fork } from "redux-saga/effects";

function* watchFetchUser() {
  yield fork(fetchUser); // 并发启动 fetchUser saga
}

5. join

等待由 fork 启动的任务完成。

javascript
import { fork, join } from "redux-saga/effects";

function* mainSaga() {
  const task = yield fork(fetchUser);
  yield join(task); // 等待 fetchUser 完成
}

6. race

创建一组并行运行的任务,并返回第一个完成的任务的结果。

javascript
import { race, call, put } from "redux-saga/effects";

function* fetchWithTimeout() {
  const { response, timeout } = yield race({
    response: call(Api.fetchData),
    timeout: call(delay, 1000),
  });

  if (response) {
    yield put({ type: "FETCH_SUCCEEDED", payload: response });
  } else if (timeout) {
    yield put({ type: "FETCH_FAILED", error: "Request timed out" });
  }
}

7. all

并行执行多个任务,并等待所有任务完成。

javascript
import { all, call } from "redux-saga/effects";

function* fetchMultipleResources() {
  yield all([call(fetchUsers), call(fetchPosts), call(fetchComments)]);
}

8. select

从 Redux store 中选择状态片段。

javascript
import { select } from "redux-saga/effects";

function* incrementIfOdd() {
  const currentState = yield select();
  if (currentState.counter % 2 === 1) {
    yield put({ type: "INCREMENT" });
  }
}

// 或者选择特定的状态片段
function* incrementIfOdd() {
  const counter = yield select((state) => state.counter);
  if (counter % 2 === 1) {
    yield put({ type: "INCREMENT" });
  }
}

9. cancel

取消一个正在运行的任务。

javascript
import { cancel, fork } from "redux-saga/effects";

function* mainSaga() {
  const task = yield fork(fetchUser);
  // 取消任务
  yield cancel(task);
}

10. delay

延迟一定时间后继续执行。

javascript
import { delay } from "redux-saga/effects";

function* delayedAction() {
  yield delay(1000); // 延迟1秒
  yield put({ type: "ACTION_DELAYED" });
}

使用示例

以下是一个完整的例子,展示了如何使用 redux-saga 来处理异步 API 请求:

javascript
import { takeLatest, call, put, all } from "redux-saga/effects";
import Api from "./api";

// worker saga: 将被 `takeLatest` 调用
function* fetchUser(action) {
  try {
    const user = yield call(Api.fetchUser, action.payload.userId);
    yield put({ type: "USER_FETCH_SUCCEEDED", user });
  } catch (error) {
    yield put({ type: "USER_FETCH_FAILED", error });
  }
}

// watcher saga: 监听特定 action 类型并启动 worker saga
function* watchFetchUser() {
  yield takeLatest("FETCH_USER", fetchUser);
}

// root saga: 组合多个 watcher sagas
export default function* rootSaga() {
  yield all([watchFetchUser()]);
}

总结

  • redux-saga 的作用:管理 Redux 应用中的副作用,特别是异步操作。
  • 指令的作用:提供了丰富的工具集来声明式地处理各种副作用,包括函数调用、action dispatch、并发控制等。
  • 使用方法:通过 redux-saga 提供的指令,你可以编写更清晰、可测试的异步逻辑。

Released under the MIT License.