当前位置: 首页 > news >正文

【Redux】自己动手实现redux-thunk

1. 前言

        在原始的redux里面,action必须是plain object,且必须是同步。而我们经常使用到定时器,网络请求等异步操作,而redux-thunk就是为了解决异步动作的问题而出现的。

2. redux-thunk中间件实现源码
function createThunkMiddleware(extra) {return ({ dispatch, getState}) => next => action => {if(typeof action === 'function') {return action(dispatch, getState, extra);}return next(action);        }
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
2.1 此处dispatch = compose(...chain)(store.dispatch)
  • action(dispatch)中的这个dispatch可能并不是store.dispatch
  • action(dispatch)执行后,如果action函数体使用dispatch({...}),动作{...}也会层层传递下去,直到传递给store.dispatch({...})
  • 举个例子,比如说dispatch= f(g(h(store.dispatch)))),那么action(dispatch)函数体中执行到dispatch({...}),动作传递过程是: f(g(h(store.dispatch)))({...}) -> g(h(store.dispatch))({...}) -> h(store.dispatch)({...}) -> store.dispatch({...})
2.2 此处next的对应关系

        继续举个例子,比如说dispatch = f(g(h(store.dispatch))))

  • 如果当前中间件指向f,则next对应g(h(store.dispatch))
  • 如果当前中间件指向g,则next对应h(store.dispatch)
  • 如果当前中间件指向h,则next对应store.dispatch(真实的dispatch)
3. redux中applyMiddleware方法源码
export const applyMiddleware = (...middlewares) => {return createStore => (reducer, preloadedState) => {const store = createStore(reducer, preloadedState);let dispatch = () => {throw new Error('xxxx');};const middlewareAPI = {getState: store.getState,dispatch: (action, ...args) => dispatch(action, ...args)};const chain = middlewares.map(middleware => middleware(middlewareAPI));dispatch = compose(...chain)(store.dispatch);return {...store,dispatch}}
};export const compose = (...funcs) => {if(funcs.length === 0) {return arg => arg;}if(funcs.length === 1) {return funcs[0];}return funcs.reduce((prev, cur) => {return (...args) => {prev(cur(...args));} });
}
4. redux中createStore增加第3个参数
export const createStore = (reducer, preloadedState, enhancer) => {// 初始化statelet state = preloadedState;// 保存监听函数const listeners = [];// 返回store当前保存的stateconst getState = () => state;// 通过subscribe传入监听函数const subscribe = (listener) => {listeners.push(listener);}// 执行dispatch,通过reducer计算新的状态state// 并执行所有监听函数const dispatch = (action) => {state = reducer(state, action);for(const listener of listeners) {listener();}}!state && dispatch({});if(enhancer) {return enhancer(createStore)(reducer, preloadedState);}return {getState,dispatch,subscribe,}
}

注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~  

http://www.lryc.cn/news/273273.html

相关文章:

  • ElasticSearch使用Grafana监控服务状态-Docker版
  • VS Code 如何调试Python文件
  • day06、SQL语言之概述
  • 3D目标检测(教程+代码)
  • 让设备更聪明 |启英泰伦离线自然说,开启智能语音交互新体验!
  • React Hooks之useState、useRef
  • 提供电商Api接口-100种接口,淘宝,1688,抖音商品详情数据安全,稳定,支持高并发
  • git的使用 笔记1
  • 基于SpringBoot的医疗挂号管理系统
  • prometheus与zabbix监控的对比介绍
  • 详解全志R128 RTOS安全方案功能
  • 【MySQL】WITH AS 用法以及 ROW_NUMBER 函数 和 自增ID 的巧用
  • 基于SpringBoot的在线考试系统源码和论文
  • 基于Spring Boot的美妆分享系统:打造个性化推荐、互动社区与智能决策
  • Axure医疗-住院板块,住院患者原型预览,新增医护人员原型预览,新增病房原型预览,选择床位原型预览,主治医生原型预览,主治医生医嘱原型预览
  • 前端实战第一期:悬浮动画
  • Python学习笔记(五)函数、异常处理
  • Vue实现模糊查询
  • 【十一】【C++\动态规划】1218. 最长定差子序列、873. 最长的斐波那契子序列的长度、1027. 最长等差数列,三道题目深度解析
  • 主板部件
  • 2023年度学习总结
  • 服务器感染了.kann勒索病毒,如何确保数据文件完整恢复?
  • 使用results.csv文件数据绘制mAP对比图
  • 【算法刷题】## 算法题目第1讲:双指针处理数组题目 带视频讲解
  • 达梦数据:数字化时代,国产数据库第一股终于到来?
  • selenium4.0中常见操作方式50条
  • 如何解决使用融云音视频时由于库冲突导致编译不通过的问题
  • ISP 基础知识积累
  • Android Studio新手实战——深入学习Activity组件
  • [足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-10奈奎斯特稳定性判据-Nyquist Stability Criterion