React的做用View层次的前端框架,天然少不了不少中间件(Redux Middleware)作数据处理, 而redux-saga就是其中之一,目前这个中间件在网上的资料仍是比较少,估计应用的不是很普遍,可是若是使用得当,将会事半功倍的效果,下面仔细介绍一个这个中间件的具体使用流程和应用场景。javascript
Redux-saga是Redux的一个中间件,主要集中处理react架构中的异步处理工做,被定义为generator(ES6)的形式,采用监听的形式进行工做。前端
使用npm进行安装:java
npm install --save redux-saga
或者使用yarn:react
yarn add redux-saga
Effect 是一个 javascript 对象,能够经过 yield 传达给 sagaMiddleware 进行执行在, 若是咱们应用redux-saga,全部的 Effect 都必须被 yield 才会执行。npm
举个例子,咱们要改写下面这行代码:redux
yield fetch(url);
应用saga:api
yield call(fetch, url)
等待 dispatch 匹配某个 action 。promise
好比下面这个例子:前端框架
.... while (true) { yield take('CLICK_Action'); yield fork(clickButtonSaga); } ....
触发某个action, 做用和dispatch相同:架构
yield put({ type: 'CLICK' });
具体的例子:
import { call, put } from 'redux-saga/effects' export function* fetchData(action) { try { const data = yield call(Api.fetchUser, action.payload.url) yield put({type: "FETCH_SUCCEEDED", data}) } catch (error) { yield put({type: "FETCH_FAILED", error}) } }
做用和 redux thunk 中的 getState 相同。一般会与reselect库配合使用。
有阻塞地调用 saga 或者返回 promise 的函数,只在触发某个动做。
循环监听某个触发动做,咱们一般会使用while循环替代。
import { takeEvery } from 'redux-saga/effects' function* watchFetchData() { yield takeEvery('FETCH_REQUESTED', fetchData) }
对于触发多个action的时候,只执行最后一个,其余的会自动取消。
import { takeLatest } from 'redux-saga/effects' function* watchFetchData() { yield takeLatest('FETCH_REQUESTED', fetchData) }
一般fork 和 cancel配合使用, 实现非阻塞任务,take是阻塞状态,也就是实现执行take时候,没法向下继续执行,fork是非阻塞的,一样可使用cancel取消一个fork 任务。
function* authorize(user, password) { try { const token = yield call(Api.authorize, user, password) yield put({type: 'LOGIN_SUCCESS', token}) } catch(error) { yield put({type: 'LOGIN_ERROR', error}) } } function* loginFlow() { while(true) { const {user, password} = yield take('LOGIN_REQUEST') yield fork(authorize, user, password) yield take(['LOGOUT', 'LOGIN_ERROR']) yield call(Api.clearItem('token')) } }
上面例子中,当执行
yield fork(authorize, user, password)
的同时,也执行了下面代码,进行logout的监听操做。
yield take(['LOGOUT', 'LOGIN_ERROR'])
引入saga:
import { call, put, take, select } from 'redux-saga/effects';
建立任务:
/** * Created by Richard on 1/11/17. */ import { call, put, take, select } from 'redux-saga/effects'; import { get, getWordUrl } from '../../utils/api'; import {successFetchData } from './WordAction'; export default function* wordFlow() { try { const data = yield call(get, getWordUrl()); yield put(successFetchData(data)); } catch (e){ } }
建立saga:
import { fork } from 'redux-saga/effects'; import wordFlow from './containers/word-view/WordSaga'; export default function* rootSaga() { yield [ fork(wordFlow) ]; }
与redux中间件进行整合:
/** * Created by Richard on 12/29/16. */ import { applyMiddleware, createStore, compose } from 'redux'; import createSagaMiddleware from 'redux-saga'; import reducers from '../reducers'; import sagas from '../sagas'; //建立saga middleware const sagaMiddleware = createSagaMiddleware(); const middlewares = compose(applyMiddleware(sagaMiddleware)autoRehydrate()); export default function configureStore() { const store = createStore(reducers, undefined, middlewares); //运行全部已经注册的saga sagaMiddleware.run(sagas); return store; }
下面就能够正常监听状态了。
传统意义讲,咱们不少业务逻辑要在action中处理,因此会致使action的处理比较混乱,难以维护,并且代码量比较大,若是咱们应用redux-saga会很大程度上简化代码, redux-saga 自己也有良好的扩展性, 很是方便的处理各类复杂的异步问题