Redux中間件組合方法

中間件

https://redux.js.org/glossary#middlewarejavascript

中間件在發送端 action端點 和 處理方reducer的端點之間。css

主要負責將async action轉換爲action, 或者記錄action日誌。html

A middleware is a higher-order function that composes a dispatch function to return a new dispatch function. It often turns async actions into actions.java

Middleware is composable using function composition. It is useful for logging actions, performing side effects like routing, or turning an asynchronous API call into a series of synchronous actions.redux

 

import { createStore, applyMiddleware } from 'redux'
import todos from './reducers'

function logger({ getState }) {
  return next => action => {
    console.log('will dispatch', action)

    // Call the next dispatch method in the middleware chain.
    const returnValue = next(action)

    console.log('state after dispatch', getState())

    // This will likely be the action itself, unless
    // a middleware further in chain changed it.
    return returnValue
  }
}

const store = createStore(todos, ['Use Redux'], applyMiddleware(logger))

store.dispatch({
  type: 'ADD_TODO',
  text: 'Understand the middleware'
})
// (These lines will be logged by the middleware:)
// will dispatch: { type: 'ADD_TODO', text: 'Understand the middleware' }
// state after dispatch: [ 'Use Redux', 'Understand the middleware' ]

 

 

http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.htmlapi

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 這兩步之間,添加了其餘功能。app

 

應用多箇中間件

https://redux.js.org/api/applymiddlewareless

applyMiddleware(...middleware)

Middleware is the suggested way to extend Redux with custom functionality. Middleware lets you wrap the store's dispatch method for fun and profit. The key feature of middleware is that it is composable. Multiple middleware can be combined together, where each middleware requires no knowledge of what comes before or after it in the chain.async

 

Arguments

  • ...middleware (arguments): Functions that conform to the Redux middleware API. Each middleware receives Store's dispatch and getState functions as named arguments, and returns a function. That function will be given the next middleware's dispatch method, and is expected to return a function of action calling next(action) with a potentially different argument, or at a different time, or maybe not calling it at all. The last middleware in the chain will receive the real store's dispatch method as the next parameter, thus ending the chain. So, the middleware signature is ({ getState, dispatch }) => next => action.

 

Returns

(Function) A store enhancer that applies the given middleware. The store enhancer signature is createStore => createStore but the easiest way to apply it is to pass it to createStore() as the last enhancer argument.

 

應用中間件函數實現, 注意其中 對於middlewares數組, 使用compose函數進行組合, 其串聯方式是從 右 到 左, 即最右邊的被包裹爲最裏層,最早執行, 最左邊的被包裹到最外面, 最後執行。

https://www.cnblogs.com/liaozhenting/p/10166671.html

export default function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    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.`
      )
    }

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

 

以下圖很形象:

https://zhuanlan.zhihu.com/p/20597452

 

 

 

 compose

https://www.cnblogs.com/liaozhenting/p/10166671.html

/**
 * Composes single-argument functions from right to left. The rightmost
 * function can take multiple arguments as it provides the signature for
 * the resulting composite function.
 *
 * @param {...Function} funcs The functions to compose.
 * @returns {Function} A function obtained by composing the argument functions
 * from right to left. For example, compose(f, g, h) is identical to doing
 * (...args) => f(g(h(...args))).
 */

export default 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)))
}

 

與pipe正好相反:

const pipe = (...fns) => {
  return (args) => {
    return fns.reduce((args, fn) => {
      return fn(args)
    }, args)
  }
}

const toUpper = (value) => {
  return value.toUpperCase();
}

const addFont = (value) => {
  return 'hello plus!' + value;
}

console.log(pipe(addFont,toUpper)('test'));
// HELLO PLUS!TEST

 

跟pip函數對比

console.log(pipe(addFont,toUpper)('test')); // HELLO PLUS!TEST console.log(compose(addFont,toUpper)('test')); // hello plus!TEST

 

underscore compose

http://www.bootcss.com/p/underscore/#compose

compose_.compose(*functions)
返回函數集 functions 組合後的複合函數, 也就是一個函數執行完以後把返回的結果再做爲參數賦給下一個函數來執行. 以此類推. 在數學裏, 把函數 f(), g(), 和 h() 組合起來能夠獲得複合函數 f(g(h()))

var greet    = function(name){ return "hi: " + name; };
var exclaim  = function(statement){ return statement.toUpperCase() + "!"; };
var welcome = _.compose(greet, exclaim);
welcome('moe');
=> 'hi: MOE!'
相關文章
相關標籤/搜索