redux中的reducer函数主要目的是制定更新规则,如果reduce中的action是一个异步的或者是一个函数的时候就会报错实例如下
调用方法
   const delayed = ()=>{
        store.dispatch(()=>{
            setTimeout(() => {
                store.dispath({type:"ADD"})    
            }, 1000);
        })
    }
执行结果
image.png
报错原因说action必须使用明确的action,你可以使用带中间件的异步action
- 使用中间件
需要安装3个中间件- 第一步
 
 
yarn add redux-logger redux-promise redux-thunk
- 第二步修改createStore方法
 
import {createStore, applyMiddleware, combineReducers} from "redux";
 import thunk from "redux-thunk";
 import logger from "redux-logger";
import promise from "redux-promise";
function countReducer(state=0,action) {
  debugger
    switch(action.type){
        case "ADD":
            return state+=1
        case "MINUS":
            return state -=1
        default:
            return state
    }
}
const store = createStore(countReducer,applyMiddleware(promise,thunk,logger))
export default store
修改完成,在执行dispatch为函数或者为promise都可以
- 注意 logger最好写在最后,不然不能很好的捕捉日志
 
仿写中间件 logger thunk 和promise
- 代码思路:所谓的中间件其实就是对现有的createStore进行增强,返回的结果也应该和createStore保持一致。增强只是说对dispatch进行增强。同时也需要执行一遍中间件(函数)
 
- 修改createStore函数
 
export default function createStore(reducer,enhancer){
//enhancer 表示applyMiddleware 执行结果
    if (enhancer){
        //enhancer(createStore) 返回一个函数,相当于把createStore函数传递到函数中,在此执行这个函数,参数为reducer
        return enhancer(createStore)(reducer)
    }
    // reducer 表示一个函数
    let currentState;
    let currentListeners =[]
    function getState() {
        return currentState
    }
    function  dispatch(action) {
        currentState = reducer(currentState,action)
        currentListeners.forEach(listener =>listener())
    }
    function subscribe(listener) {
        currentListeners.push(listener)
        return () =>{
            const index = currentListeners.indexOf(listener)
            currentListeners.splice(index,1)
        }
    }
    dispatch({type:"REDXXXXXXXX"})
    return {
        getState,
        subscribe,
        dispatch
    }
}
- 创建 applyMiddleware文件并导出
 
export default function applyMiddleware(...middlewares) {
//这个地方可以改为  createStore  =>reducer =>{} 函数样式
    return createStore => {
        return reducer => {
            const store = createStore(reducer) //调用createStore函数,返回值为
        // store  = {getState, subscribe,dispatch}
            let dispatch = store.dispatch //取出store中的dispath函数,主要目的是传递给中间件(函数使用)
            const midApi = { //定义一个中间件使用的对象
                getState: store.getState,
                dispatch: action => dispatch(action)
            }
            // 把midApi 传递给中间件
            const middlewareChain = middlewares.map(middleware => middleware(midApi)) //注意,这个地方需要结合中间件函数一起看, 返回next => action =>{}函数总数为2 一个为thunk的返回值一个为logger返回值
            let res = compose(...middlewareChain) //返回一个函数,logger的
         dispatch =res(store.dispatch)//执行compose函数 dispatch 返回的就是thunk中的 action =>{} 函数
            // 返回增强的store,其实把dispatch增强就行了 
            return {
                ...store,
                dispatch
            };
        }
    }
}
function compose(...funs) {
    // 这个空数组的兼容情况
    if (funs.length === 0) {
        return arg => arg;
    }
    if (funs.length === 1) {
        return funs[0];
    }
    // 这个返回值是个函数
    let r=  funs.reduce((a, b) => (...args) => a(b(...args)));
    return r
}
- 中间件(函数)的创建
 
import {createStore, applyMiddleware, combineReducers} from "redux";
// import thunk from "redux-thunk";
// import logger from "redux-logger";
// import promise from "redux-promise";
// import  {createStore,applyMiddleware} from '../vRedux/index'
function countReducer(state=0,action) {
  debugger
    switch(action.type){
        case "ADD":
            return state+=1
        case "MINUS":
            return state -=1
        default:
            return state
    }
}
// ,
const store = createStore(countReducer,applyMiddleware(thunk,logger))
// thunk处理异步
function thunk({dispatch, getState}) {
    // next 通过comose函数,next其实就是logger函数,action函数就是dispatch中的函数dispatch(A) A =action,首先要判断action是对象还是函数,如果是函数的话,首先执行函数,因为在action(dispatch, getState);函数体重,仍然有dispatch函数的调用,它会再次进入这个函数,只不过这个参数为对象,因为next =logger函数返回的action=>{}函数,所以进入logger函数
    return next => action => {
      if (typeof action === "function") {
        return action(dispatch, getState);
      }
      return next(action);
    };
  }
  
  // ! 注意了: logger一定要放在applyMiddleware最后一个参数,因为放在前面的话,可能或没有type值,
  // ! 比如说thunk处理的函数也是’action‘,但是就没有type值
  function logger({dispatch, getState}) {
    return next => action => {
       //logger函数中 next为createStore 方法中dispatch函数,这是因为在compose函数调用的时候传递的为store.dispatch函数,action 表示操作类型action={type:XXX}
      console.log("start *************************************");
      console.log(action.type + "执行啦"); //sy-log
      // dispatch执行前的state
      const prevState = getState(); //这表示当前的state状态
      console.log("prev state" + prevState, JSON.stringify(prevState)); //sy-log
  
      // 相当于dispatch执行完了,数据已经发生变化
      const returnValue = next(action); //正式执行了dispatch(action)函数,state发生了变化
      const nextState = getState(); //最新的状态
      console.log("next state" + nextState, JSON.stringify(nextState)); //sy-log
  
      console.log("end *************************************");
  
      return returnValue;
    };
  }
export default store












网友评论