摘要:当你应用了中间件,在触发一个操作的时候,操作就会经过先经过中间件,最终再形成。以其中两个中间件为例,说明下,一个触发一个动作的时候,代码的执行逻辑。
为了解析中间件,先看一下几个中间件是什么样子,怎么用,运行起来的原理是什么?
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.2promise中间件
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.3logger中间件
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和初始状态initialState生成初始化store,并提供了一些列操作的接口,像dispatch等
怎么做的呢?参考Redux-creatStore/compose
本文重点讲解中间件的执行过程和原理
中间件的执行原理和koa中间件的执行原理类似,但是不是洋葱型的,而是半个洋葱,因为redux是单向执行的,走过去就完事了。
当你应用了中间件,在触发一个action操作的时候,action操作就会经过先经过中间件,最终再形成dispatch(action)。
以其中两个中间件为例,说明下,一个触发一个action动作的时候,代码的执行逻辑。
thunk:是允许dispatch一个函数,而不是一个对象
假如说异步打印一个日志。
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和getState两个。
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 => {}
明白了么?
附录 compsoe// 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))) }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/98334.html
摘要:通过创建将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替中间件。 redux-saga框架使用详解及Demo教程 前面我们讲解过redux框架和dva框架的基本使用,因为dva框架中effects模块设计到了redux-saga中的知识点,可能有的同学们会用dva框架,但是对redux-saga又不是很熟悉,今天我们就来简单的讲解下saga框架的主要API和如何配合redux框...
摘要:或者兄弟组件之间想要共享某些数据,也不是很方便传递获取等。后面要讲到的就是通过让各个子组件拿到中的数据的。所以,确实和没有什么本质关系,可以结合其他库正常使用。 本文介绍了react、redux、react-redux之间的关系,分享给大家,也给自己留个笔记,具体如下: React 一些小型项目,只使用 React 完全够用了,数据管理使用props、state即可,那什么时候需要引入...
摘要:执行完后,获得数组,,它保存的对象是图中绿色箭头指向的匿名函数,因为闭包,每个匿名函数都可以访问相同的,即。是函数式编程中的组合,将中的所有匿名函数,,组装成一个新的函数,即新的,当新执行时,,从左到右依次执行所以顺序很重要。 前言 It provides a third-party extension point between dispatching anaction, and t...
阅读 922·2023-04-26 01:34
阅读 3356·2023-04-25 20:58
阅读 3258·2021-11-08 13:22
阅读 2107·2019-08-30 14:17
阅读 2521·2019-08-29 15:27
阅读 2673·2019-08-29 12:45
阅读 2996·2019-08-29 12:26
阅读 2810·2019-08-28 17:51