Saga 模式通过 Generator 函数实现可读、可测试、可中断的异步流程管理,核心是 yield 暂停并返回 Effect 描述操作,由中间件执行;支持监听、取消、竞态处理与流程编排。
JavaScript 中的 Saga 模式通过 Generator 函数实现对复杂异步流程(如多步骤请求、错误恢复、并发控制、取消操作)的可读、可测试、可中断的管理。它不直接处理 Promise,而是把异步逻辑“暂停”在 yield 处,由中间件(如 redux-saga)接管执行与调度。
Generator 是 Saga 的核心执行载体
Generator 函数用
function*
声明,配合
yield
暂停执行,并返回一个迭代器对象。Saga 就是一系列被 yield 暂停的 Effect(如 call、put、take),它们本身不执行异步操作,只描述“要做什么”。
yield call(api.fetchUser, id) —— 描述“调用 fetchUser 并等待结果”,实际执行由 saga middleware 完成
yield take('USER_LOGIN_REQUEST') —— 描述“等待某个 action 被 dispatch”,挂起直到匹配
yield race({ login: call(loginApi), timeout: delay(5000) }) —— 描述“登录或超时,任一完成即结束”
Saga 解决传统异步方案的痛点
对比 async/await 或纯 Promise 链,Saga 在以下场景更清晰可控:
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
监听全局动作
:比如在任意时刻收到 LOGOUT,立即取消所有进行中的请求(通过 fork + cancel 实现)
多路分支与竞态处理
:用户快速切换 tab,前一个请求应自动取消,避免状态错乱(takeLatest 效果)
流程编排与重试
:登录失败后自动弹窗 → 等待用户点击重试 → 最多重试 3 次 → 失败则跳转错误页
测试友好
:Saga 函数返回纯对象序列(Effect),可逐条断言 yield 结果,无需 mock 时间或网络
一个典型可取消的登录 Saga 示例
下面是一个带加载、错误、取消逻辑的登录流程:
立即学习
“
Java免费学习笔记(深入)
”;
关键要点与注意事项
Saga 必须注册到 store(通过 applyMiddleware(createSagaMiddleware())),否则 yield 不会被拦截执行
所有异步副作用必须用 call / cps / fork 等 Effect 包裹,直接写 fetch() 不会暂停,也无法被取消
避免在 Saga 中直接修改 state 或调用 this.setState;所有状态变更应通过 put 发送 action
注意内存泄漏:fork 启动的子任务若未正确 cancel 或 done,可能持续监听或轮询
function* loginFlow() {
while (true) {
const { payload } = yield take('LOGIN_REQUEST');
const task = yield fork(authorize, payload);
const action = yield take(['LOGIN_SUCCESS', 'LOGIN_FAILURE', 'LOGOUT']);
if (action.type !== 'LOGIN_SUCCESS' && action.type !== 'LOGIN_FAILURE') {
yield cancel(task); // 收到 LOGOUT,取消登录任务
}
}
}
function* authorize({ username, password }) {
try {
const token = yield call(api.login, { username, password });
yield put({ type: 'LOGIN_SUCCESS', token });
} catch (err) {
yield put({ type: 'LOGIN_FAILURE', error: err.message });
}
}
