Redux 数据流程中间件使用指南之 saga

阅读时长 9 分钟读完

前言

在 Redux 中,action 触发的流程是:组件 dispatch action,store 接收 action 并通过 reducer 处理 action 中携带的数据,最后返回新的 state。但在实际应用中,我们可能会需要更丰富、更复杂的流程,例如异步请求、定时任务等,此时 Redux 中间件就派上用场了。本文将重点介绍 Redux 中一款名为 saga 的中间件。

Saga 简介

saga(中文名为剧情) 是 Redux 的一个中间件,是一个基于 Generator 函数 的 saga 或 task 管理器,通常用于解决异步操作的问题。Saga 可以非常方便地管理异步流程的代码,包括发起异步请求、管理错误等等。

Saga 提供了一个基于 Generator 函数的 DSL(域特定语言),来定义数据流的处理方式,使用基于 CSP(Communicating Sequential Processes)的方式进行操作,使得我们写异步流程的代码更加简单、容易测试。

Saga 的安装

安装 Saga 非常简单,只需在项目根目录下执行以下命令即可:

或者使用 yarn:

Saga 的使用

下面我们将介绍基本的 Saga 使用方式。首先,我们需要创建一个 Saga generator 函数,用于指示 Saga 如何处理 action:

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

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

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

上述代码中,我们创建了一个 Saga generator 函数 mySaga,用于处理名为 USER_FETCH_REQUESTED 的 action。通过 takeEvery 函数,我们将监听该 action,在 action 触发时执行 fetchUser 函数。

fetchUser 函数中,我们通过 call 函数来调用异步请求函数 Api.fetchUsercall 将返回一个 promise,用于处理异步请求的结果。如果请求成功,则通过 put 发送 USER_FETCH_SUCCEEDED action,否则发送 USER_FETCH_FAILED action。

接着,我们需要在应用中使用 applyMiddleware 函数,将 Saga 中间件应用到 Redux store 中:

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

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

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

通过 createSagaMiddleware 创建一个 Saga 中间件实例,并将其应用到 store 中。使用 sagaMiddleware.run 函数来启动 Saga,开始监听并处理 action。

Saga 的进阶应用

除了基本的使用方式,Saga 还提供了更丰富的 API 来满足我们处理复杂异步流程的需求。下面我们将通过一个具体的示例来介绍 Saga 的各种用法。

我们考虑实现一个简单的计数器,用户点击按钮后,每隔 1 秒钟自增一次。实现该功能,我们需要使用 Saga 来管理异步请求和计时器操作。

首先,我们需要创建一个 Redux store,并应用 Saga 中间件:

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

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

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

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

接着,我们编写 rootSaga,在其中创建两个 saga:

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

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

  -
-

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

  -
-

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

在上述代码中,我们先定义了一个 Saga 函数 startCountingSaga,它通过 call(delay, 1000) 实现阻塞一秒钟的功能,再通过 put(incrementCount(1)) 更新计数器的值。我们将使用 startCountingSaga 来实现计时器,将它放在一个死循环中,直到接收到停止计时的请求。

接着,我们定义了另一个 Saga 函数 startCountingActionSaga,它用于接收 START_COUNTING_ACTION action,启动计时器,并更新状态为 counting。最后,该 Saga 函数更新状态为 notCounting,表示计时器已经停止。

最后,我们编写管理器组件 Counter,它包含两个按钮和一个计数器:

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

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

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

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

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

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

在上述代码中,我们通过 connect 函数连接了 Redux store,将计数器和状态值传递给组件,并处理 startCounting 和 stopCounting 两个按钮的点击事件,分别发送启动计时器和停止计时器的 action。

到此为止,我们已经完成了具有异步流程的计时器,使用 Saga 可以使得异步代码更加高效、清晰,更加容易测试和维护。

总结

本文详细介绍了 Redux 中间件 Saga 的使用方法,通过基于 Generator 函数的 DSL,可以使得我们编写异步流程的代码更加容易、高效。Saga 提供了丰富的 API,用于处理异步请求、管理计时器等复杂的异步流程。Saga 在实际应用中得到了广泛的使用,使用 Saga 可以使得我们的代码更加易于测试和维护。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/649f8c3b48841e9894be5ec0

纠错
反馈