redux基礎知識 | redux(二)javascript
在上一篇文章中,咱們經實現了一個基本的redux,那若是咱們想在redux中實現異步的操做怎麼辦?java
好比下面的操做react
pages/ReduxPage.jsgit
import React, { Component } from 'react'
import store from '../store/'
export default class ReduxPage extends Component {
componentDidMount() {
this.unsubscribe = store.subscribe(() => {
this.forceUpdate()
})
}
componentWillUnmount() {
if(this.unsubscribe) {
this.unsubscribe()
}
}
asyAdd = () => {
store.dispatch((dispatch,getState) => {
setTimeout(() => {
dispatch({type: 'ADD', payload: 1})
}, 1000)
})
}
promiseAdd = () => {
store.dispatch(Promise.resolve({type: "MINUS", payload: 1}));
}
render() {
return(
<div> <h3>Reduxpage</h3> <p>{count}</p> <button onClick={this.asyAdd}>異步+</button> <button onClick={this.promiseAdd}>promise-</button> </div>
)
}
}
複製代碼
上面的操做咱們有兩個異步的操做,分別是是setTimeout和Promise。因爲咱們的action觸發了之後,就會立馬去reducer裏面執行state的更新,因此咱們想要實現異步的操做,就必須在dispatch的時候,去作一些操做。github
在store裏面,有個方法叫作applyMiddleware(),它能夠接收一些參數,二接受的這些參數,就是咱們處理異步的中間件,咱們看一下怎麼使用的。redux
import { createStore, applyMiddleware } from 'redux';
import logger from 'react-logger';
import thunk from 'react-thunk';
import rdPromise from 'react-promise'
const countReducer = (state = 0, action) => {
const {type, payload} = action
switch(type) {
case 'ADD':
return state + payload;
case 'MINUS':
return state - payload;
default:
return state
}
}
const store = createStore(
countReducer,
applyMiddleware(thunk, logger, rdPromise)
)
export default store;
複製代碼
applyMiddleware()接收了三個參數:promise
這樣子,咱們上面的異步操做按鈕就能夠正常的工做了,下面讓咱們看看源碼如何實現的。bash
Jreact/createStore.jsapp
export default function createStore(reducer, enhancer) {
if(enhancer) {
return enhancer(createStore)(reducer)
}
}
複製代碼
在createStore裏面,咱們須要判斷一下createStore的第二個參數,也就是applyMiddleware,有的話,就把createStore和reducer傳給它,咱們須要在內部去使用這兩個參數。異步
Jreact/applyMiddleware.js
export default function applyMiddleware(...middlewares) {
return createStore => reducer => {
const store = createStore(reducer)
let dispatch = store.dispatch
const midApi = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
const middlewareChain = middlewares.map(md => md(midApi))
dispatch = compose(...middlewareChain)(store.dispatch);
return {
...store,
dispatch
}
}
}
// 聚合函數
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg;
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce((a, b) => (...args) => {
return a(b(...args));
});
}
複製代碼
applyMiddleware(...middlewares)就是接收的thunk, logger, rdPromise這幾個參數,而後在裏面對dispatch作了增強。咱們對middlewares作了便利,也就是thunk, logger, rdPromise,他們會接收getState和dispatch,而後在每一箇中間件的內部獨立處理本身的邏輯,處理完成之後會造成一個middlewareChain,使用一個聚合函數compose,把middlewareChain裏面的函數聚合一個,增強了dispatch,最後返回出去,這樣就能夠在dispatch的時候,作一些操做了。
下面是三個中間件的實現
Jreact/thunk.js
export default function thunk({dispatch, getState}) {
return next => action => {
if(typeof action === 'function') {
return action(dispatch, getState)
}
return next(action)
}
}
複製代碼
Jreact/logger.js
export default function logger({getState}) {
return next => action => {
console.log('prevState', getState());
const newState = next(action)
console.log('nextState', getState());
return newState
}
}
複製代碼
Jreact/rdPromise.js
import { isFSA } from 'flux-standard-action';
import isPromise from 'is-promise';
export default function rdPromise({dispatch}) {
return next => action => {
if(!isFSA(action)) {
return isPromise(action) ? action.then(dispatch) : next(action)
}
return next(action)
}
}
複製代碼
這是三個函數,經過聚合函數依次執行他們,就能夠了。
至此,redux的源碼就講的差很少了