前言
在 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 非常简单,只需在项目根目录下执行以下命令即可:
npm install redux-saga
或者使用 yarn:
yarn add redux-saga
Saga 的使用
下面我们将介绍基本的 Saga 使用方式。首先,我们需要创建一个 Saga generator 函数,用于指示 Saga 如何处理 action:
-- -------------------- ---- ------- ------ - ---- --------- - ---- -------------------- --------- -------- - ----- --------------------------------- ----------- - --------- ----------- - --- - ----- ---- - ----- -------------------- ----- ---------- ----------------------- ----- ------- - ----- --- - ----- ---------- -------------------- -------- ------------ - -
上述代码中,我们创建了一个 Saga generator 函数 mySaga
,用于处理名为 USER_FETCH_REQUESTED
的 action。通过 takeEvery
函数,我们将监听该 action,在 action 触发时执行 fetchUser
函数。
在 fetchUser
函数中,我们通过 call
函数来调用异步请求函数 Api.fetchUser
, call
将返回一个 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