React15 - redux-saga 中fork作用详解

在 Redux-Saga 中,fork 是一个非常重要的 Effect 创建器,它用于执行非阻塞的任务调用。

简单来说,fork 的作用是:让 Saga 启动一个子任务,并且父 Saga 不会等待这个子任务结束,会立即继续执行后续代码。

下面从几个方面详细解释 fork 的作用和特点:

1. 核心特性:非阻塞调用

这是 forkcall 最本质的区别。

  • call 是阻塞的:当 Saga 执行到 yield call(fn, ...args) 时,它会停下来等待 fn 这个任务执行完毕,拿到返回结果后,才会继续执行下一行代码。
  • fork 是非阻塞的:当 Saga 执行到 yield fork(fn, ...args) 时,它会立即启动 fn 任务,然后不等它完成,立刻就继续执行 yield fork 后面的代码。

示例对比:

import { call, fork, delay } from 'redux-saga/effects';

function* taskA() {
  yield delay(2000);
  console.log('任务A完成');
}

function* sagaWithCall() {
  console.log('开始执行 Call');
  yield call(taskA); // 阻塞!会在这里等待2秒钟
  console.log('Call 结束'); // 2秒后才打印
}

function* sagaWithFork() {
  console.log('开始执行 Fork');
  yield fork(taskA); // 非阻塞!立即继续往下执行
  console.log('Fork 结束'); // 马上打印,不等 taskA 完成
}

2. 返回一个 Task 对象

yield fork(...) 表达式执行后,会返回一个 Task 对象。这个对象代表了被启动的那个子任务,你可以通过这个对象对子任务进行后续的管理。

import { fork, cancel, delay } from 'redux-saga/effects';

function* backgroundTask() {
  while (true) {
    yield delay(1000);
    console.log('后台任务运行中...');
  }
}

function* mainSaga() {
  // 启动一个后台任务,并获取它的 task 句柄
  const task = yield fork(backgroundTask);

  // 3秒后,我们想要取消这个后台任务
  yield delay(3000);
  yield cancel(task); // 使用 task 句柄来取消它
}

3. 错误处理与隔离

fork 创建的子任务拥有独立的执行上下文。这意味着:

  • 子任务内部抛出的错误不会直接冒泡到父 Saga。
  • 父 Saga 的错误也不会直接导致子任务中断(除非父 Saga 被终止并连带取消了子任务)。
  • 这种隔离性让错误处理更加精细。

4. 实现并行执行

虽然 fork 本身是立即返回的,但它常被用来实现任务的并行执行。如果你有几个互不依赖的任务,可以先用 fork 把它们都启动起来,然后再用 join(另一个 Effect,用于等待一个 fork 任务完成)来等待它们全部结束。

import { fork, join, delay } from 'redux-saga/effects';

function* task1() {
  yield delay(2000);
  console.log('任务1完成');
  return '结果1';
}
function* task2() {
  yield delay(1000);
  console.log('任务2完成');
  return '结果2';
}

function* parallelSaga() {
  // 同时启动两个任务
  const task1Obj = yield fork(task1);
  const task2Obj = yield fork(task2);

  // 等待它们两个都完成
  const result1 = yield join(task1Obj);
  const result2 = yield join(task2Obj);

  console.log(result1, result2); // '结果1', '结果2'
}

注:all Effect 是更常用的并行模式,但 fork + join 提供了更灵活的控制,比如可以在任务启动后、等待完成前做其他事情。

总结:什么时候用 fork?

  • 需要非阻塞启动:当你启动一个任务后,不想阻塞当前 Saga 的执行流,希望立即去做别的事情。
  • 启动长期运行的后台任务:例如启动一个监听 WebSocket 消息、定时轮询 API 的守护进程。
  • 需要任务句柄进行控制:当后续可能需要 cancel(取消)、join(等待)这个任务时。
  • 实现更复杂的并行与错误处理模式:当你需要更精细地控制多个子任务的生命周期时。
posted @ 2026-03-15 17:18  箫笛  阅读(1)  评论(0)    收藏  举报