Redux中間件與異步操做

基本流程

1.建立store,帶有三個方法:store.dispatch,store.subscribe,store.getStateredux

import { applyMiddleware ,createStore } from 'redux';
const store = createStore(
    reducer,
    applyMiddleware(thunk, logger)
);

2.view發出dispatch->action數組

del = () => {
    store.dispatch({
        type: 'DEL',
        data: this.state.count - 1
    });
}

3.reducer處理action數據
每次dispatch後return的數據即store.getState()獲得的數據,即一個新的state.
因此state是一個對象,每次都是上次返回的值.
因此用Object.assign({}, state, {count: action.data})服務器

export default (state = {}, action) => {
    switch (action.type) {  // state即返回的新狀態,新的state即本次的返回值,因此每次都是往空的對象裏,先推state,再新增屬性或改變原來屬性的值
        case 'ADD':
            return Object.assign({}, state, {count: action.data});
        case 'ADD2':
            return Object.assign({}, state, {count: action.data});
        case 'ADD3':
            return Object.assign({}, state, {count: action.data});  
        case 'DEL':
            return Object.assign({}, state, {count: action.data});
        case 'AJAX':
            return Object.assign({}, state, {res: action.data.res});
        default:
            return {
                count: 0,
                res: 'aaaa'
            };
    }
}

4.view層經過store.subscribe()方法設置監聽函數,一旦state發生變化,就會自定執行這個函數.
在這個函數裏setState,就會觸發整個組件的render.app

store.subscribe(() => { // subscribe即,每一次dispatch,都會觸發reducer處理數據,即觸發store.subscribe
    this.setState({
        count: store.getState().count,  // reducer返回新的state,即state的值被改變state = 1
        res: store.getState().res
    });
});

異步操做

1.用戶發出Action,Reducer函數算出新的State,View從新渲染.
2.異步操做怎麼辦? Action發出之後,Reducer當即算出State,這叫作同步;Action發出之後,過一段時間再執行Reducer,這就是異步.
怎樣才能Reducer在異步操做結束後自動執行呢?這就要用到新的工具:中國件(middleware)
3.中間件
只有發送Action的這個步驟,即store.dispatch()方法,能夠添加功能.
能夠對store.dispatch進行以下改造.異步

let next = store.dispatch;

store.dispatch = function dispatchAndLog(action) {
    console.log('dispatching', action);
    next(action);
    console.log('next state', store.getState());
}

上面代碼中,對store.dispatch進行了重定義,在發送Action先後添加了打印功能,這就是中間件的雛形.
中間件就是一個函數,對store.dispatch方法進行了改造,在發出Action和執行Reducer這兩步之間,添加了其餘功能.
4.中間件的用法
redux-logger提供一個生成器createLogger,能夠生成日誌中間件logger,而後,將它放在applyMiddleware方法中,
傳入createStore方法,就完成了store.dispatch()的功能加強.函數

import { applyMiddleware ,createStore } from 'redux';
import { createLogger } from 'redux-logger';
import thunk from 'redux-thunk';

const logger = createLogger();

const store = createStore(
    reducer,
    applyMiddleware(thunk, logger)
);

5.applyMiddleware
applyMiddleware是Redux的原生方法,做用是將全部中間件組成一個數組,依次執行.
6.異步操做的基本思路
操做開始時,送出一個Action,觸發State更新爲'正在操做'狀態,從新渲染.
操做結束後,再送出一個Action,觸發State更新爲'操做結束',view再一次從新渲染.工具

redux-thunk中間件

1.異步操做至少要送出兩個Action,用戶觸發第一個Action,這個跟同步操做同樣,沒有問題.
如何才能在操做結束時,系統自動送出第二個Action呢?this

add3 = () => {
    store.dispatch(dispatchAction(this.state.count + 3));
}
function dispatchAction(count) {
    return (dispatch) => {
        dispatch({
            type: 'ADD3',
            data: count
        });
    }
}

dispatchAction是一個Action Creater,返回一個函數,這個函數執行後,發出一個action,而後執行異步操做,拿到結果後,再次dispatch,發出一個Action.
dispatchAction返回了一個函數,而普通的action creator默認返回一個對象.
返回的函數的參數是dispatch和getState這兩個redux方法.
action是由store.dispatch方法發送的,而store.dispatch方法正常狀況下,參數只能是對象,不能是函數.
這時,就使用redux-thunk中間件,改造dispatch,使得後者能夠接受函數做爲參數.spa

使用redux-thunk發Async Action的例子

1.首先,這是個關於action creator的解釋.
什麼是action creator? 返回action的函數.
爲何要用action creator?圖個方便吧.日誌

function changeNum(count) {
    return {
        type: 'ADD2',
        data: count
    }
}
add2 = () => {
    store.dispatch(changeNum(this.state.count + 2));
}

2.Thunk的作法就是擴展了這個action creator.Thunk容許action creator返回一個函數,並且這個函數第一個參數是dispatch.因此不光改造action creator,若是你要用thunk,你還要把它放進middleware裏去,這樣函數類型的action就被thunk middleware捕獲,根據你的函數邏輯,再去dispatch常規的action.這樣Async Action其實就是發Ajax以前dispatch一發,收到服務器響應後dispatch一發,報錯的話再來dispatch一發.

相關文章
相關標籤/搜索