redux深入理解之中介軟體 middleware

2022-03-06 12:08:03 字數 4241 閱讀 3975

本文**請看本人github,

關於redux運用,請看之前一篇文章

reduce() 方法接收乙個函式作為累加器(accumulator),陣列中的每個值(從左到右)開始縮減,最終為乙個值。

arr.reduce([callback, initialvalue])
關於reduce的用法,這裡不再做多述,可以去這裡檢視

看如下例子:

let arr = [1, 2, 3, 4, 5];

// 10代表初始值,p代表每一次的累加值,在第一次為10

// 如果不存在初始值,那麼p第一次值為1

// 此時累加的結果為15

let sum = arr.reduce((p, c) => p + c, 10); // 25

// 轉成es5的寫法即為:

var sum = arr.reduce(function(p, c) , 10);

下面我們再來看乙個reduce的高階擴充套件。現在有這麼乙個資料結構,如下:

let school = ,]},

, ,

]} ]

};

比如我想取到這個學校的第乙個班級的第乙個老師的名字,可能你會這樣寫:

school.classes[0].teachers[0].name
這樣不就行了麼?so easy!是哦,這樣寫"毫無問題",這個毫無問題的前提是你已經知道了這個值確實存在,那麼如果你不知道呢?或許你要這麼寫:

school.classes &&

school.classes[0] &&

school.classes[0].teachers &&

school.classes[0].teachers[0] &&

school.classes[0].teachers[0].name

我去,好大一坨,不過要在深層的物件中取值的場景在工作中真真實實存在呀?怎麼辦?逛知乎逛到乙個大神的解決方案,如下:

const get = (p, o) => p.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), o);

// call

get('classes', 0, 'teachers', 0, 'name', school); // 張二蛋

是不是很簡單,用reduce這個方法優雅地解決了這個問題。

講了這麼久的reduce,這不是講redux麼?這就尷尬了,下面我們就來看看為什麼要講這個reduce函式。去github上找到redux原始碼,會看到乙個compose.js檔案,帶上注釋共22行,其中就用到了reduce這個函式,那麼這個函式是用來做啥的?可以看一看:

export default function compose(...funcs) 

if (funcs.length === 1)

return funcs.reduce((a, b) => (...args) => a(b(...args)))

}

return (createstore) => (reducer, preloadedstate, enhancer) =>

chain = middlewares.map(middleware => middleware(middlewareapi))

dispatch = compose(...chain)(store.dispatch)

return

}}

const logger = store => next => action =>
當我們建立了乙個store的時候,我們是這樣呼叫的:

let middlewares = [loggermiddleware, thunkmiddleware, ...others];
那麼傳給compose的funcs實際上就是包含這樣的函式的乙個陣列:

function(next) 

}

當把這樣的乙個陣列傳給compose會發生什麼樣的化學反應呢?稍微看一下應該不難看出,最終會返回乙個函式,這個函式是通過了層層middleware的加工,最終的形態仍如上面的這個樣子。注意,此時的next(action)並未執行,當執行了

compose(...chain)(store.dispatch)
之後,返回的樣子是這樣的:

function(action)
各位看官們,看出了一點點什麼東西了麼?好像createstore中的dispatch呀,沒錯,這其實也是乙個dispatch,只是這個dispatch正一觸即發,再等待乙個機會。我們有這麼乙個數量加1的action,類似這樣的:

export function addcount() 

}// 下面我們來觸發一下

dispatch(addcount());

沒錯,此時的dispatch執行啦,最外層的dispatch執行了會發生什麼樣的反應呢?看下面:

return next(action);

// 這個next就是dispatch函式,只不過這個dispatch函式在每次執行的時候,會保留

// 上乙個middleware傳遞的dispatch函式的引用,因此會一直的傳遞下去,

// 直到最終的store.dispatch執行

那麼我們去createstore中去看看dispatch函式的定義:

function dispatch(action)  finally 

// ...

return action

}

找到這一句

currentstate = currentreducer(currentstate, action);
當執行了這一步的時候,這一刻,原本傳遞過來的initialstate值已經改變了,那麼就會層層執行middleware之後的操作,還記得我們在middleware中這樣寫了麼:

const logger = store => next => action =>
這就是為什麼我們會在next執行之後,會取到store中的state的原因。

非同步的action寫法上可能會和立即執行的action不一樣,例如是這樣的:

// 定義的非純函式,提供非同步請求支援

// 需要在sotre中使用thunkmiddleware

export function refresh() , 3000);

});}

}

為什麼要使用thunkmiddleware呢,我們去找一找thunkmiddleware中到底寫了什麼?

function createthunkmiddleware(extraargument) ) => next => action => 

return next(action);

};}const thunk = createthunkmiddleware();

thunk.withextraargument = createthunkmiddleware;

export default thunk;

短短14行**,看這一句:

if (typeof action === 'function')
如果action的型別為function的話,那麼就直接執行啦,實際上就是將乙個非同步的操作轉化成了兩個立即執行的action,只是需要在非同步前和非同步後分別傳送狀態。為什麼要分解呢?如果不分解會是什麼樣的情況?還記得這一行**嗎?

currentreducer(currentstate, action);
這裡的reducer只接受純函式,只接受純函式,只接受純函式,重要的事情說三遍。所以你傳個非純函式是個什麼鬼?那不是直接走switchdefault了麼?所以得到的state依舊是之前的state,沒有任何改變。

redux深入理解之中介軟體 middleware

本文 請看本人github,關於redux運用,請看之前一篇文章 reduce 方法接收乙個函式作為累加器 accumulator 陣列中的每個值 從左到右 開始縮減,最終為乙個值。arr.reduce callback,initialvalue 關於reduce的用法,這裡不再做多述,可以去這裡檢...

深入理解redux中介軟體

摘自 please call me hr redux middleware 是 redux 的乙個 advanced feature.這個概念並不是很新奇,以為在 koa 裡面早已經實現過了.對比與原生的redux middleware koa 的 middleware 差不多相當於是爸爸級的 le...

理解redux中介軟體

1.reducers 函式如何建立和聚合 2.action建立函式如何如何包裹在dispatch函式中 3.如何給預設的dispatch方法增加中介軟體能力 js context 中介軟體由函式組合的形式建立,實現與主要執行任務正交的功能。tips 類似的有裝飾器模式 在 redux middlew...