redux 提供了相似後端 Express 的中間件概念。
最適合擴展的是redux中的 store.dispatch 方法,中間件實際就是經過 override redux的store.dispatch() 完成
將 action -> reducer 過程變爲 action -> middlewares -> reducer 如:git
let next = store.dispatch; store.dispatch = function dispatchAndLog(action) { console.log('dispatching', action); next(action); console.log('next state', store.getState()); }
redux提供了 applyMiddleware 方法便於添加中間件github
applyMiddleware的源碼:redux
export default function applyMiddleware(...middlewares) { middlewares = middlewares.slice() middlewares.reverse() // Transform dispatch function with each middleware. middlewares.forEach(middleware => // 因爲每次middle會直接返回返回函數,而後在這裏賦值給store.dispatch, // 下一個middle在一開始的時候,就能夠經過store.dispatch拿到上一個dispatch函數 store.dispatch = middleware(store) ) }
經過middleware將 store.dispatch 進行擴展後端
middleware會返回一個函數:return store => dispatch => action => {}
promise
Action寫法:app
// 寫法一:名稱相同,參數不一樣 { type: 'FETCH_POSTS' } { type: 'FETCH_POSTS', status: 'error', error: 'Oops' } { type: 'FETCH_POSTS', status: 'success', response: { ... } } // 寫法二:名稱不一樣 { type: 'FETCH_POSTS_REQUEST' } { type: 'FETCH_POSTS_FAILURE', error: 'Oops' } { type: 'FETCH_POSTS_SUCCESS', response: { ... } }
異步State結構:異步
let state = { // ... isFetching: true,// 正在獲取數據 didInvalidate: true,// 是否過時 lastUpdated: 'xxxxxxx'// 上次更新時間 };
createStore(reducer, enhancer)
或 createStore(reducer, preloadedState, enhancer)
redux-logger 可清晰記錄 preState action nextState time等信息。async
示例:ide
import { createStore, applyMiddleware } from 'redux' import createLogger from 'redux-logger' import rootReducer from './reducers' let store = createStore(rootReducer, applyMiddleware(createLogger));
redux-thunk 用來優化redux中的異步操做。函數
在store.dispatch 的方法參數只支持js對象(即Action),使用redux-thunk將支持參數爲一個函數。
或者說 redux-thunk 使得 action 從一個對象變成一個函數。
函數簽名:(dispatch, getState) => {}
示例:
import { createStore, applyMiddleware } from 'redux' import thunkMiddleware from 'redux-thunk' import rootReducer from './reducers' let store = createStore(rootReducer, applyMiddleware(thunkMiddleware)); store.dispatch( dispatch => { dispatch({type:'CLICK_START',data:res}) fetch('xx') .then(res => dispatch({type:'CLICK_END',data:res})); } )
實際上,redux-thunk 的做用是讓 Action Creator方即可以返回函數,這樣讓項目中的同步異步Action Creator調用能夠保持一致
redux-saga 相比thunk 功能顯得全面,精細。
saga 是一個常駐進程,在複雜任務 及 長時事務場景很是適用。
這裏經過2個action 來展現 saga
示例:
import createSagaMiddleware, { delay } from 'redux-saga' import { all, put, takeEvery, takeLatest } from 'redux-saga/effects' function* helloSaga() { yield delay(1000) console.log('hello world') } function* incrementAsync() { yield delay(1000) yield put({ type: 'click' }) } function* rootSaga() { yield all([ takeEvery('hello', helloSaga), takeLatest('async', incrementAsync) ]) } let sagaMiddleware = createSagaMiddleware(); let store = createStore(rootReducer, applyMiddleware(sagaMiddleware)) sagaMiddleware.run(rootSaga); store.dispatch({ type: 'hello' }); store.dispatch({ type: 'async' });
支持異步的還有redux-promise 等