随着前端应用越来越复杂,数据流管理也变得越来越困难。Redux 是一个为解决这一问题而生的工具,它使得我们可以高效地管理应用的数据流,同时 Redux-saga 是一个处理异步操作的库,可以有效地解决异步操作导致的数据流混乱问题。本文将详细介绍 Redux-saga 的使用方法,并通过示例代码演示。
安装
首先需要安装 Redux 和 redux-saga:
npm install redux redux-saga
基本概念
Generator
首先需要了解 Generator 。Generator 是 ES6 中的一个新特性,在函数执行时可以暂停和恢复。使用 yield
关键字可以返回多个值,如:
-- -------------------- ---- ------- --------- ----- - ----- -- ----- -- ------ -- - ----- --------- - ------ ------------------------------ -- - ------ -- ----- ----- - ------------------------------ -- - ------ -- ----- ----- - ------------------------------ -- - ------ -- ----- ---- -
Effect
Redux-saga 中常见的是 effect,简单的说,effect 是一个简单对象,包括了要在 saga 中执行的指令,最常见的 effect 有 put
和 call
,它们分别代表对应的 action 和异步操作。
Saga
Saga 是一个长期运行的进程,主要用于响应操作并发送 action。 Saga 是使用 generator 来实现异步操作的。
使用
创建 Saga
创建 Saga 需要一个 generator 函数和一个 watcher 函数。我们首先定义一个 worker 函数,并在 generator 函数中使用 yield call(worker, args)
调用它:
function* worker() { const data = yield call(fetchData); yield put({ type: 'FETCH_DATA_SUCCESS', payload: data }); } function* watchSaga() { yield takeEvery('FETCH_DATA', worker); }
其中 takeEvery
是一个辅助函数,它监听指定的 action,当该 action 被 dispatch 时,watcher 函数就会开始执行 worker 函数。在 worker 函数中,我们可以使用 effect 来调用异步函数 fetchData
,并将返回的数据通过 put
发送一个 action。
function fetchData() { return fetch('https://www.example.com/data') .then(res => res.json()) .then(data => data) .catch(error => error); }
运行 Saga
我们需要将 Saga 与 Redux store 绑定起来:
import createSagaMiddleware from 'redux-saga'; import { applyMiddleware, createStore } from 'redux'; import rootReducer from './reducer'; import { watchSaga } from './saga'; const sagaMiddleware = createSagaMiddleware(); const store = createStore(rootReducer, applyMiddleware(sagaMiddleware)); sagaMiddleware.run(watchSaga);
我们需要使用 createSagaMiddleware
创建一个中间件,然后调用 run
方法来运行 Saga。
使用 takeEvery 控制流程
takeEvery
可以控制并行处理每个 action,当一个 action type 被 dispatch 时,它能够启动多个 worker 并行地处理。一般来说,这是最常用的控制流程的方式。除了 takeEvery,还有其他的辅助函数,例如:takeLatest、takeLeading 等。
import { takeEvery } from 'redux-saga/effects'; function* watchFetchData() { yield takeEvery('FETCH_DATA', worker); }
使用 call 执行异步函数
通常我们使用 fetch 或 axios 等库从服务器异步获取数据,而使用 call
effect 可以确保异步操作顺序正确:
function* fetchDataWorker() { try { const data = yield call(fetchData); yield put({ type: 'FETCH_DATA_SUCCESS', payload: data }); } catch (error) { yield put({ type: 'FETCH_DATA_FAILURE', error }); } }
如果 fetchData
返回一个 promise,则 call effect 会在 promise resolve 后恢复 generator 函数的执行。
使用 put 发送 action
使用 put
effect 非常简单,它表示 dispatch 一个 action,我们可以像调用 Redux 的 dispatch
相同的方法来使用它:
function* loginWorker(action) { try { const user = yield call(api.login, action.payload); yield put({ type: 'LOGIN_SUCCESS', payload: user }); } catch (error) { yield put({ type: 'LOGIN_FAILURE', error }); } }
使用 select 访问状态
使用 select
effect 可以访问 store 中的数据:
function* fetchDataWorker() { const state = yield select(); const data = yield call(fetchData, state.token); yield put({ type: 'FETCH_DATA_SUCCESS', payload: data }); }
监听多个 action
我们也可以使用 take
监听一个或多个 action,然后在处理完成后重新开始监听:
function* watchFetchData() { while (true) { const action = yield take(['FETCH_DATA', 'REFRESH_DATA']); yield call(fetchDataWorker, action); } }
总结
在本文中,我们学习了如何使用 Redux-saga 处理异步操作,以及如何使用 call
、put
、select
和多个辅助函数来创建 Saga。Redux-saga 的使用可以帮助我们更好地处理数据流,避免了回调地狱。希望本文对您有所帮助!
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64714bdd968c7c53b0f31dd3