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

wordpress手机端底部菜单主题郑州seo学校

wordpress手机端底部菜单主题,郑州seo学校,为什么做网站要用谷歌浏览器,建筑工程网络计划称为由于一直用业界封装好的如redux-logger、redux-thunk此类的中间件,并没有深入去了解过redux中间件的实现方式。正好前些时间有个需求需要对action执行时做一些封装,于是借此了解了下Redux Middleware的原理。* 中间件概念 首先简单提下什么是中间件&…
由于一直用业界封装好的如redux-logger、redux-thunk此类的中间件,并没有深入去了解过redux中间件的实现方式。正好前些时间有个需求需要对action执行时做一些封装,于是借此了解了下Redux Middleware的原理。

* 中间件概念

首先简单提下什么是中间件,该部分与下文关系不大,可以跳过。来看眼这个经典的图。

clipboard.png

不难发现:

  1. 不使用middleware时,在dispatch(action)时会执行rootReducer,并根据actiontype更新返回相应的state
  2. 而在使用middleware时,简言之,middleware会将我们当前的action做相应的处理,随后再交付rootReducer执行。

简单实现原理

比如现有一个action如下:

function getData() {return {api: '/cgi/getData',type: [GET_DATA, GET_DATA_SUCCESS, GET_DATA_FAIL]}
}

我们希望执行该action时可以发起相应请求,并且根据请求结果由定义的type匹配到相应的reducer,那么可以自定义方法处理该action,因此该方法封装成中间件之前可能是这样的:

async function dispatchPre(action, dispatch) {const api = action.api;const [ fetching_type, success_type,  fail_type] = action.type;// 拉取数据const res = await request(api);// 拉取时状态dispatch({type: fetching_type});// 成功时状态if (res.success) {dispatch({type: success_type, data: res.data});console.log('GET_SUCCESS');}// 失败时状态if (res.fail) {dispatch({type: fail_type});console.log('GET_FAIL');};
}// 调用: dispatchPre(action(), dispatch)

那如何封装成中间件,让我们在可以直接在dispatch(action)时就做到这样呢?可能会首先想到改变dispatch指向

// 储存原来的dispatch
const dispatch = store.dispatch;
// 改变dispatch指向
store.dispatch = dispatchPre;
// 重命名
const next = dispatch;

截止到这我们已经了解了中间件的基本原理了~

源码分析

了解了基本原理能有助于我们更快地读懂middleware的源码。
业务中,一般我们会这样添加中间件并使用。

createStore(rootReducer, applyMiddleware.apply(null, [...middlewares]))

接下来我们可以重点关注这两个函数createStoreapplyMiddleware

CreateStore

// 摘至createStore
export function createStore(reducer, rootState, enhance) {...if (typeof enhancer !== 'undefined') {if (typeof enhancer !== 'function') {throw new Error('Expected the enhancer to be a function.')}/*若使用中间件,这里 enhancer 即为 applyMiddleware()若有enhance,直接返回一个增强的createStore方法,可以类比成react的高阶函数*/return enhancer(createStore)(reducer, preloadedState)}...
}

ApplyMiddleware

再看看applyMiddleware做了什么,applyMiddleware函数非常简单,就十来行代码,这里将其完整复制出来。

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)}// 1、将store对象的基本方法传递给中间件并依次调用中间件const chain = middlewares.map(middleware => middleware(middlewareAPI))// 2、改变dispatch指向,并将最初的dispatch传递给composedispatch = compose(...chain)(store.dispatch)return {...store,dispatch}}
}

执行步骤

根据源码,我们可以将其主要功能按步骤划分如下:

1、依次执行middleware

middleware执行后返回的函数合并到一个chain数组,这里我们有必要看看标准middleware的定义格式,如下

export default store => next => action => {}// 即
function (store) {return function(next) {return function (action) {return {}}}
}

那么此时合并的chain结构如下

[    ...,function(next) {return function (action) {return {}}}
]

2、改变dispatch指向。

想必你也注意到了compose函数,compose函数如下:
[...chain].reduce((a, b) => (...args) => a(b(...args)))
实际就是一个柯里化函数,即将所有的middleware合并成一个middleware,并在最后一个middleware中传入当前的dispatch

*compose可能会看得有点蒙,不理解柯里化函数的同学可以跳到一个例子读懂compose先了解下。

// 假设chain如下:
chain = [a: next => action => { console.log('第1层中间件') return next(action) }b: next => action => { console.log('第2层中间件') return next(action) }c: next => action => { console.log('根dispatch') return next(action) }
]

调用compose(...chain)(store.dispatch)后返回a(b(c(dispatch)))
可以发现已经将所有middleware串联起来了,并同时修改了dispatch的指向。
最后看一下这时候compose执行返回,如下

dispatch = a(b(c(dispatch)))// 调用dispatch(action)
// 执行循序
/*1. 调用 a(b(c(dispatch)))(action) __print__: 第1层中间件2. 返回 a: next(action) 即b(c(dispatch))(action)3. 调用 b(c(dispatch))(action) __print__: 第2层中间件4. 返回 b: next(action) 即c(dispatch)(action)5. 调用 c(dispatch)(action) __print__: 根dispatch6. 返回 c: next(action) 即dispatch(action)7. 调用 dispatch(action)
*/

*一个例子读懂compose

上文提到compose是个柯里化函数,可以看成是将所有函数合并成一个函数并返回的函数。
例如先定义3个方法

function A(x){return x + 'a'
}function B(y){return y + 'b'
}function C(){return 'c'
}var d = [...A, b, C].reduce((a, b) => (d) => {console.log(d, a, b); a(b(d))})d // 打印d// f (d) { console.log(d, a, b); return a(b(d)) }d('d') // 调用d/** d* f(d) { console.log(d, a, b); return a(b(d)) }* f C() { return 'c' }
*//** c* f A(x) { return x + 'a' }* f B(y) { return y + 'b' }
*/

不难发现,使用闭包,在调用d的时候,将ab函数储存在了内存中,调用时会依次将数组从右至左的函数返回做为参数传递给下一个函数使用

http://www.lbrq.cn/news/2480275.html

相关文章:

  • js网站记住密码怎么做性能优化工具
  • 网站app下载平台怎么做的线上广告接单平台
  • 网站左侧悬浮导航上海网站外包
  • 网站建设有哪些软件如何在互联网上做推广
  • world做网站企业网站推广渠道
  • 海北公司网站建设建站平台哪个比较权威
  • 网站界面设计尺寸规范自媒体平台有哪些
  • 关于 政府门户网站 建设管理深圳市网络营销推广服务公司
  • 邓州网站推广百度公司的企业文化
  • 高端网站制作网站建设实时积分榜
  • 天马行空网站建设百度官网下载安装到桌面上
  • 网站建设公司湖南多用户建站平台
  • 网站建设开发合同模板下载湖南网站优化
  • 杨彪网站建设免费网站建设哪个好
  • 网站的开发环境设计seo排名系统
  • 企业网站建设套餐价格百度信息流推广和搜索推广
  • 简述网站建设方案类型网销怎么销售的
  • 可以做立体图形的网站做seo需要哪些知识
  • 织梦 网站模板全网营销系统怎么样
  • 贵阳专业做网站公司疫情防控最新通告
  • 耿马网站建设360关键词排名推广
  • 宝鸡网站建设公司都有哪些百度搜索排行榜风云榜
  • amaze ui做网站泉州网站建设优化
  • 做近代史纲要题的网站最近新闻小学生摘抄
  • 专门做dnf补丁的网站谷歌账号注册入口官网
  • 网站上线怎么做百度官网首页官网
  • 建设政府网站的费用网络营销简介
  • b2b2c 网站seo网站搜索优化
  • 广州工程项目沈阳seo排名外包
  • 网店免费注册潍坊seo建站
  • 网络编程2(应用层协议,传输层协议)
  • linux内核电源管理
  • sqli-labs通关笔记-第21关 字符型Header-Cookie SQL注入(单引号括号闭合 base64编码绕过 手工注入+脚本注入两种方法)
  • Spring AI Alibaba Video 示例
  • 2025年02月11日 Go生态洞察:Go 1.24 发布亮点全面剖析
  • STM32与ADS1220实现多通道数据采集的完整分析和源程序