Redux中間部品の原理について詳しく説明する.


中間部品を解析するために、いくつかの中間部品がどのように使われていますか?運行の原理は何ですか?
1、ミドルウェアはどんな形ですか?
1.2 thunk中間部品
function createThunkMiddleware(extraArgument) {

  return ({ dispatch, getState }) => next => action => {
    //      ,     
    if (typeof action === 'function') {
        return action(dispatch, getState, extraArgument);
    }
    //     ,        
    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;
1.2 promiseミドルウェア
import isPromise from 'is-promise';
import { isFSA } from 'flux-standard-action';

export default function promiseMiddleware({ dispatch }) {
  return next => action => {
    if (!isFSA(action)) {
      return isPromise(action) ? action.then(dispatch) : next(action);
    }

    return isPromise(action.payload)
      ? action.payload
          .then(result => dispatch({ ...action, payload: result }))
          .catch(error => {
            dispatch({ ...action, payload: error, error: true });
            return Promise.reject(error);
          })
      : next(action);
  };
}
1.3 loggerミドルウェア
const defaultLogger = ({ dispatch, getState } = {}) => {
  if (typeof dispatch === 'function' || typeof getState === 'function') {
    return createLogger()({ dispatch, getState });
  }
};
function createLogger(options = {}) {
  const loggerOptions = Object.assign({}, defaults, options);

  const {
    logger,
    stateTransformer,
    errorTransformer,
    predicate,
    logErrors,
    diffPredicate,
  } = loggerOptions;

  if (typeof logger === 'undefined') {
    return () => next => action => next(action);
  }

  import { logger } from 'redux-logger'
  const store = createStore(
      reducer,
      applyMiddleware(logger))
    
  import { createLogger } from 'redux-logger'
  const logger = createLogger({
      // ...options
    });
  const store = createStore(
      reducer,
      applyMiddleware(logger));
      
  return () => next => action => next(action);
  }

  const logBuffer = [];

  return ({ getState }) => next => (action) => {
    if (typeof predicate === 'function' && !predicate(getState, action)) {
      return next(action);
    }
    const logEntry = {};

    logBuffer.push(logEntry);

    logEntry.started = timer.now();
    logEntry.startedTime = new Date();
    logEntry.prevState = stateTransformer(getState());
    logEntry.action = action;

    let returnedValue;
    if (logErrors) {
      try {
        returnedValue = next(action);
      } catch (e) {
        logEntry.error = errorTransformer(e);
      }
    } else {
      returnedValue = next(action);
    }

    logEntry.took = timer.now() - logEntry.started;
    logEntry.nextState = stateTransformer(getState());

    const diff = loggerOptions.diff && typeof diffPredicate === 'function'
      ? diffPredicate(getState, action)
      : loggerOptions.diff;

    printBuffer(logBuffer, Object.assign({}, loggerOptions, { diff }));
    logBuffer.length = 0;

    if (logEntry.error) throw logEntry.error;
    return returnedValue;
  };
}
export { defaults, createLogger, defaultLogger as logger };

export default defaultLogger;
2、ミドルウェアの使い方
const store = createStore(rootReducer, initialState, 
    applyMiddleware(thunk),
    ... ...
);
簡単に言えば、createStoreはこのようなことをしました.目的はあなたが伝えてきたreducerと初期状態initial Stateから初期化storeを生成し、列操作のインターフェースを提供しました.dispachなどはどうしますか?Redux-creat Store/compose本文を参照して、中間部品の実行過程と原理を重点的に説明します.
3、中間部品の運行原理
中間部品の実行原理はkoa中間部品の実行原理と似ていますが、玉ねぎ型ではなく、半玉ねぎです.reduxは一方通行ですので、歩いて行けば大丈夫です.中間部品を適用して、一つのaction操作をトリガすると、action操作は先に中間部品を経由して、最終的にdispatchを形成します.二つの中間部品を例にとって、一つのaction動作をトリガする場合、コードの実行ロジックを説明します.thunk:オブジェクトではなく、dispatchの関数を許可します.例外的にログを印刷します.
3.1中間部品の内部ロジック
const store = createStore(reducer, preloadedState, enchancer);

//        ,      action;
//           creatStore           
// enchancer          ,  applyMiddleware        

function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
  
    //     store      ,        ,     ,       store
    const store = createStore(...args)
    let dispatch = () => {
      throw new Error(
        `Dispatching while constructing your middleware is not allowed. ` +
          `Other middleware would not be applied to this dispatch.`
      )
    }
    //  getState、dispatch     
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    //               ,       
    // next => {}
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    //       ,        
    // action => {}
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

//          
//        a b
// a(b(store.dispatch))
return enchancer(createStore)(reducer, preloadedState);

//     thunk   
({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
        return action(dispatch, getState);
    }
    return next(action);
  };
上記の操作を経て、中間包装後のstoreはどうなりますか?仮に中間部品がa b cで中間部品がない場合はこのようになります.
store = {
    dispatch,
    ... ...,
    subscribe,
    getState
}
中間包装を経て、storeが変わりました.
store = {
    dispatch: a(b((store.dispatch))),
    ... ...,
    subscribe,
    getState
}
まとめとは、中間部品ごとにオリジナルのstoreのdispatchを配付し、中間部品の関数をネストして実行することです.
3.2 actionをトリガする場合、論理を実行する
非同期印刷ログをトリガする機能を設定します.
  • アプリケーション中間
  • const store = createStore(rootReducer, initialState, 
        applyMiddleware(thunk)
    );
    上の操作を経て、今のstoreは
    {
        dispatch: action => {
            if (typeof action === 'function') {
                return action(dispatch, getState, extraArgument);
            }
            return next(action);
        },
        ... ...,
        subscribe,
        getState
    }
  • action関数
  • このlogNextを実行すると、関数を返します.関数のパラメータはdispatchとget Stateの2つです.
    const logNext = () => (dispatch, getState) => {
        setTimeout(
            dispatch({
                type: 'LOG',
                payload: {
                    content: '        '
                }})
            ,5000);
    }
  • 実行プロセス
  • ---->
    store.dispatch(logNext())  //       ,        
    ----> 
    (dispatch, getState) => {
        setTimeout(
            dispatch({
                type: 'LOG',
                payload: {
                    content: '        '
                }})
            ,5000);
    } 
    ---->
    redux-thunkはパッケージ関数であり、store.dispatchの関数が複数ある場合、実行過程はどのようになりますか?ポイントはnext(action)で、nextは何ですか?nextは中間の仕事ごとです.
    next => action => {}
    分かりましたか
    付録
    copsoe
    // compose           ,              
        function compose(...funcs) {
          if (funcs.length === 0) {
            return arg => arg
          }
          if (funcs.length === 1) {
            return funcs[0]
          }
            return funcs.reduce((a, b) => (...args) => a(b(...args)))
        }