redux-applyMiddleware实现理解+自定义中间件
前言:
终于好好理解了middleware。。。。
1.redux middleware提供的是位于 action 被发起之后,到达 reducer 之前的扩展点。
redux通过store.dispatch(atcion),发起一个action给store,store接收后把当前state与action一起传给reducer,所以middleware做文章的地方就是dispatch,在原生的dispatch执行之前,先进行一些列的操作。
实现middleware的方法:下面以logger中间件为例
1.手动记录(不可能会使用这种的吧)
let action = addTodo('Use Redux') console.log('dispatching', action)
store.dispatch(action)
console.log('next state', store.getState())
2.封装dispatch,
要发起action的时候,不用 dispatch 而是用 disptchAddLog()。(把这个方法放在store里面、好像还不错的样子)
function dispatchAndLog(store, action) {
console.log('dispatching', action)
store.dispatch(action)
console.log('next state', store.getState())
}
3.猴子补丁,
通过重写store.dispatch(), (重写之后,所使用的dispatch(), 已经不是原生的dispatch了,使用多个中间件,就是不断改写前一次生成的dispatch),
(注意:原生的dispatch,已经不可能找到,也就是不能单独使用原始dispatch了)
function(store) {
let next = store.dispatch
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
4.隐藏猴子补丁,
乍一看好像和猴子补丁没什么却别,但其实它把赋值的给store.dispatch的逻辑放到了中间件函数的外面,需要外面提过一个applyMiddleware辅助函数来完成插值,除此之外,真的没什么区别。(原理还是猴子补丁)
function logger(store) {
let next = store.dispatch // 我们之前的做法:
// store.dispatch = function dispatchAndLog(action) { return function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
多个中间件 的实现方式:
function applyMiddlewareByMonkeypatching(store, middlewares) {
middlewares = middlewares.slice()
middlewares.reverse() // 在每一个 middleware 中变换 dispatch 方法。
middlewares.forEach(middleware =>
store.dispatch = middleware(store)
)
}
5.移除猴子补丁,
相对隐藏猴子不同,把middleware函数里面 let next = store.dispatch ,放到函数外面 dispatch = middleware(store)(dispatch)
function logger(store) {
return function wrapDispatchToAddLogging(next) {
return function dispatchAndLog(action) {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
}
}
看一下多个中间件实现方式你就知道了,
是否发现:在 return 的 assign 之前, store.dispatch 都是原生的,并没有被改变。所以中间件里面是否可以使用store.dispatch调用原生的,(如果有需要的话),然而笔者试着调用了一下,并不行,会不断的触发,就是已经是该改变之后的了。
// 警告:这只是一种“单纯”的实现方式!
// 这 *并不是* Redux 的 API. function applyMiddleware(store, middlewares) {
middlewares = middlewares.slice()
middlewares.reverse() let dispatch = store.dispatch
middlewares.forEach(middleware =>
dispatch = middleware(store)(dispatch)
) return Object.assign({}, store, { dispatch })
}
logger中间件换成es6的箭头函数更好看
const logger = store => next => action => {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
6.redux中是现实方法
这与 Redux 中 applyMiddleware()
的实现已经很接近了,但是有三个重要的不同之处:
它只暴露一个 store API 的子集给 middleware:
dispatch(action)
和getState()
。它用了一个非常巧妙的方式来保证你的 middleware 调用的是
store.dispatch(action)
而不是next(action)
,从而使这个 action 会在包括当前 middleware 在内的整个 middleware 链中被正确的传递。这对异步的 middleware 非常有用。为了保证你只能应用 middleware 一次,它作用在
createStore()
上而不是store
本身。因此它的签名不是(store, middlewares) => store
, 而是(...middlewares) => (createStore) => createStore
。
总结:
redux提供了applyMiddleware(), 如果我们自定义中间件,也就变的很简单了
function myMiddleware = (store) => (next) => (action) => {
console.log('进入了我自己定义的中间件');
let result = next(action); // 执行下一步
// let result = store.dispatch(action); //不调用next,直接使用store.dispatch调用原生。然后是不行的,会陷入dispatch死循环。
return result;
}
applyMiddleware会帮我们执行前面两层函数。myMiddleware(store)(dispatch)
redux-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;
redux-applyMiddleware实现理解+自定义中间件的更多相关文章
- redux middleware 的理解
前言 这几天看了redux middleware的运用与实现原理,写了一个百度搜索的demo,实现了类似redux-thunk和redux-logger中间件的功能. 项目地址:https://git ...
- redux:applyMiddleware源码解读
前言: 笔者之前也有一篇关于applyMiddleware的总结.是applyMiddleware的浅析. 现在阅读了一下redux的源码.下面说说我的理解. 概要源码: step 1: apply ...
- ASP.NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介
概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要介绍了ASP.NET Core中StaticFile.Middleware ...
- ASP.NET Core 1.0 静态文件、路由、自定义中间件、身份验证简介
概述 ASP.NET Core 1.0是ASP.NET的一个重要的重新设计. 例如,在ASP.NET Core中,使用Middleware编写请求管道. ASP.NET Core中间件对HttpCon ...
- asp.net core中写入自定义中间件
首先要明确什么是中间件?微软官方解释:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?tabs=aspnet ...
- AspNetCore Mvc 自定义中间件认证
AspNetCore Mvc 自定义中间件认证 实现控制器访问验证和拦截. 1.注册政策. 例如: services.AddAuthorization(options => { options. ...
- NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介
NET Core 1.1 静态文件.路由.自定义中间件.身份验证简介 概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要 ...
- express中的中间件(middleware)、自定义中间件、静态文件中间件、路由中间件
express文档地址 什么是中间件呢(middleware)?它是谁的中间件呢? 首先我们需要了解到请求和响应, 请求就是客户端发送请求给服务器, 响应就是,服务器根据客户端的请求返回给客户端的数据 ...
- 深入理解自定义ListView
深入理解自定义ListView ListView原理 他是一个系统的原生控件,用列表的形式来显示内容.如果内容过过有1000条左右,我们可以通过手势的上下滑动来查看数据.ListView也不是爆出OO ...
随机推荐
- javascript 学习笔记之JQuery中的Deferred对象
Deffered是Jquery中的一个非常重要的对象,从1.5版本之后,Jquery中的ajax操作都基于Deffered进行了重构,这个对象的处理模式就像其他Javascript框中的Promise ...
- 上传图片预览 支持IE8+,FF,Chrome ,保留原图片比例
代码及效果:链接
- jQuery提供的小方法
jQuery提供的小方法: 1.选择器 + 事件 + 函数 = 复杂的交互 2.循环处理与选择器匹配的各个元素:each() $("#").each(function(){ ...
- PHP 关于 $GLOBALS['HTTP_RAW_POST_DATA']
PHP 关于 $GLOBALS['HTTP_RAW_POST_DATA'] 最近用微信api写接口时用到了这个,记录,下面转载开始: —————————— 这是手册里写的 总是产生变量包含有原始的 P ...
- Python 学习之urllib模块---用于发送网络请求,获取数据
1.urllib urllib是Python标准库的一部分,包含urllib.request,urllib.error,urllib.parse,urlli.robotparser四个子模块. (1) ...
- python【第十一篇】消息队列RabbitMQ、缓存数据库Redis
大纲 1.RabbitMQ 2.Redis 1.RabbitMQ消息队列 1.1 RabbitMQ简介 AMQP,即Advanced Message Queuing Protocol,高级消息队列协议 ...
- Memcache,Redis
Memcache Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度. ...
- Windows下配置g++的简单方法
需要下载名为 Cygnus的软件.下载地址: http://www.claremontmckenna.edu/math/ALee/g++/full.exe 安装完成后配好环境变量就可以用gcc, g+ ...
- win7 进程kill
文章出处:http://www.cnblogs.com/winstic/,请保留此连接 在使用windows操作时,经常会遇到一些顽固进程大占CPU,很是苦恼:今天就遇到这样的问题,刚写的一个一个分布 ...
- http server v0.1_http_webapp.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h&g ...