Redux-saga 基础知识和实现

阅读时长 7 分钟读完

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 实现。

-- -------------------- ---- -------
------ - ---------- --- - ---- ---------------------

------ --------- --------------- -
  ----- ----- ----- ----------- ---
-

------ --------- --------------- -
  ----- ----- ----- ----------- ---
-

------ --------- ---------------- -
  ----- ---------------------------- ---------------
-

------ --------- ---------------- -
  ----- ---------------------------- ---------------
-
  • watchIncrementwatchDecrement 监听 INCREMENT_ASYNCDECREMENT_ASYNC 发起的 action,并分别调用 incrementSagadecrementSaga

  • incrementSaga 调用 put({ type: 'INCREMENT' }) 时,代表将派发一次 INCREMENT action。

  • decrementSaga 调用 put({ type: 'DECREMENT' }) 时,代表将派发一次 DECREMENT action。

创建 React 组件

最后,我们需要创建一个 React 组件来将 Saga 和 React 组件连接起来。下面是一个极简的组件。

-- -------------------- ---- -------
------ ----- ---- --------
------ - ------------ ----------- - ---- --------------

-------- --------- -
  ----- ----- - ------------------- -- -------------
  ----- -------- - --------------

  ----- --------------- - -- -- -
    ---------- ----- ----------------- ---
  --

  ----- --------------- - -- -- -
    ---------- ----- ----------------- ---
  --

  ------ -
    -----
      ------------ ------------
      ------- -------------------------------------
      ------- -------------------------------------
    ------
  --
-

------ ------- --------

该组件使用 React Hook useSelectoruseDispatch 分别获取 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

纠错
反馈