Redux-saga 是一个用于管理 Redux 的副作用(异步操作,如与服务器 API 的请求或浏览器缓存或定时器等)的库。通过 redux-saga,我们可以将异步操作(side effect)和业务逻辑分开,使代码更易于测试、理解和维护。本文将介绍 redux-saga 的基本概念和用法,并通过示例代码演示实现。
基本概念
Redux-saga 的核心是 Generator 函数和 Effect。以下是 redux-saga 的常用概念:
Generator 函数
Generator 函数是 JavaScript 中的一个特殊函数,它可以被中断并恢复。执行 Generator 函数将返回一个迭代器对象,该迭代器对象可迭代返回多个值,而不仅仅是单个值。
--------- ------------- - ----- -- ----- -- ----- -- - ----- --------- - -------------- ------------------------------ -- - ------ -- ----- ----- - ------------------------------ -- - ------ -- ----- ----- - ------------------------------ -- - ------ -- ----- ----- - ------------------------------ -- - ------ ---------- ----- ---- -
Generator 函数内部可以使用 yield
语句返回值,并暂停函数的执行,等待下一次调用 next()
方法恢复执行。Generator 函数可以无限制地调用 yield
来返回多个值。
Effect
Effect 是一个对象,它描述了 Generator 函数的一种指令。Effect 可被 dispatch(发送)到 saga 中,用于控制 saga 如何处理副作用。
常用的 Effect 包括:
call(fn, ...args)
:调用函数 fn,并传递给它一些参数(args)。如果 fn 返回 Promise,则暂停后续 saga 执行,直到 Promise resolve 或 reject。如果 fn 返回一个 Generator 对象,则暂停 saga 执行,直到该 Generator 执行完成。put(action)
:发送一个 Redux action。相当于 dispatch 一个 action。select(selector)
:从 Redux store 中获取 state。take(pattern)
:暂停 saga 执行,直到一个匹配 pattern 的 action 被派发到 Redux store 中。fork(fn, ...args)
:以非阻塞方式调用函数 fn,并传递给它一些参数(args)。race(effects)
:并行地运行多个 Effect,并返回第一个完成的 Effect。cancel(task)
:取消一个 Effect。
示例说明
下面通过一个简单的 Saga 示例来演示实现。该示例使用了 Redux 和 React。
安装依赖
首先,我们需要安装需要的依赖:
--- ------- ----- ----------- ----------
创建 Store
然后,我们需要创建 Redux Store。这里将设置默认的 state 为 0,并提供两种操作增加和减少 state。当 state 改变时,组件会自动更新。
------ - ----------- - ---- -------- ----- ------------ - - ------ - -- -------- ------------- - ------------- ------- - ------ ------------- - ---- ------------ ------ - ------ ----------- - - -- ---- ------------ ------ - ------ ----------- - - -- -------- ------ ------ - - ------ ------- ---------------------
创建 Saga
接着,我们需要在 Redux Store 中使用 Saga。
下面是增加和减少 state 的 Saga 实现。
------ - ---------- --- - ---- --------------------- ------ --------- --------------- - ----- ----- ----- ----------- --- - ------ --------- --------------- - ----- ----- ----- ----------- --- - ------ --------- ---------------- - ----- ---------------------------- --------------- - ------ --------- ---------------- - ----- ---------------------------- --------------- -
watchIncrement
和watchDecrement
监听INCREMENT_ASYNC
和DECREMENT_ASYNC
发起的 action,并分别调用incrementSaga
和decrementSaga
。当
incrementSaga
调用put({ type: 'INCREMENT' })
时,代表将派发一次INCREMENT
action。当
decrementSaga
调用put({ type: 'DECREMENT' })
时,代表将派发一次DECREMENT
action。
创建 React 组件
最后,我们需要创建一个 React 组件来将 Saga 和 React 组件连接起来。下面是一个极简的组件。
------ ----- ---- -------- ------ - ------------ ----------- - ---- -------------- -------- --------- - ----- ----- - ------------------- -- ------------- ----- -------- - -------------- ----- --------------- - -- -- - ---------- ----- ----------------- --- -- ----- --------------- - -- -- - ---------- ----- ----------------- --- -- ------ - ----- ------------ ------------ ------- ------------------------------------- ------- ------------------------------------- ------ -- - ------ ------- --------
该组件使用 React Hook useSelector
和 useDispatch
分别获取 state 和 dispatch。
当用户点击“+1”时,组件会派发一个 INCREMENT_ASYNC
action,这个 action 将被 Saga 监听, Saga 会调用 incrementSaga
,并将 INCREMENT
action 派发到 Redux Store 中。
当用户点击“-1”时,组件会派发一个 DECREMENT_ASYNC
action,这个 action 将被 Saga 监听, Saga 会调用 decrementSaga
,并将 DECREMENT
action 派发到 Redux Store 中。
结论
Redux-saga 是一个非常有用的库,它使得 Redux 更容易使用,使得代码更易于测试、理解、维护。如需更深入了解请参考其官方文档,官方文档详细讲述了如何在 Saga 中处理更多的 Effect 和如何更好地控制副作用。我们希望通过本文的介绍和示例代码,您可以更好地理解和使用 redux-saga。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/66fa76dd44713626014c8dbb