React从入门到放弃之前奏(4):Redux中间件
redux 提供了类似后端 Express 的中间件概念。
最适合扩展的是redux中的 store.dispatch 方法,中间件实际就是通过 override redux的store.dispatch() 完成
将 action -> reducer 过程变为 action -> middlewares -> reducer 如:
let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action);
next(action);
console.log('next state', store.getState());
}
添加中间件
redux提供了 applyMiddleware 方法便于添加中间件
applyMiddleware的源码:
export default function applyMiddleware(...middlewares) {
middlewares = middlewares.slice()
middlewares.reverse()
// Transform dispatch function with each middleware.
middlewares.forEach(middleware =>
// 由于每次middle会直接返回返回函数,然后在这里赋值给store.dispatch,
// 下一个middle在一开始的时候,就可以通过store.dispatch拿到上一个dispatch函数
store.dispatch = middleware(store)
)
}
通过middleware将 store.dispatch 进行扩展
middleware会返回一个函数:return store => dispatch => action => {}
异步操作
- 同步操作只要发出一种 Action 即可,异步操作通常需要发出多种 Action(开始、成功、失败)
- 异步操作有2种Action写法(3种type 或者 添加erro 和 response字段)
- 异步操作的state结构调整
Action写法:
// 写法一:名称相同,参数不同
{ type: 'FETCH_POSTS' }
{ type: 'FETCH_POSTS', status: 'error', error: 'Oops' }
{ type: 'FETCH_POSTS', status: 'success', response: { ... } }
// 写法二:名称不同
{ type: 'FETCH_POSTS_REQUEST' }
{ type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
{ type: 'FETCH_POSTS_SUCCESS', response: { ... } }
异步State结构:
let state = {
// ...
isFetching: true,// 正在获取数据
didInvalidate: true,// 是否过期
lastUpdated: 'xxxxxxx'// 上次更新时间
};
使用中间件
- 使用
createStore(reducer, enhancer)或createStore(reducer, preloadedState, enhancer) - applyMiddleware的参数为中间件,某些中间件有顺序要求如:logger
redux-logger
redux-logger 可清晰记录 preState action nextState time等信息。
示例:
import { createStore, applyMiddleware } from 'redux'
import createLogger from 'redux-logger'
import rootReducer from './reducers'
let store = createStore(rootReducer, applyMiddleware(createLogger));
redux-thunk
redux-thunk 用来优化redux中的异步操作。
在store.dispatch 的方法参数只支持js对象(即Action),使用redux-thunk将支持参数为一个函数。
或者说 redux-thunk 使得 action 从一个对象变成一个函数。
函数签名:(dispatch, getState) => {}
示例:
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from './reducers'
let store = createStore(rootReducer, applyMiddleware(thunkMiddleware));
store.dispatch( dispatch => {
dispatch({type:'CLICK_START',data:res})
fetch('xx')
.then(res => dispatch({type:'CLICK_END',data:res}));
} )
实际上,redux-thunk 的作用是让 Action Creator方便可以返回函数,这样让项目中的同步异步Action Creator调用可以保持一致
redux-saga
redux-saga 相比thunk 功能显得全面,精细。
saga 是一个常驻进程,在复杂任务 及 长时事务场景非常适用。
这里通过2个action 来展示 saga
示例:
import createSagaMiddleware, { delay } from 'redux-saga'
import { all, put, takeEvery, takeLatest } from 'redux-saga/effects'
function* helloSaga() {
yield delay(1000)
console.log('hello world')
}
function* incrementAsync() {
yield delay(1000)
yield put({ type: 'click' })
}
function* rootSaga() {
yield all([
takeEvery('hello', helloSaga),
takeLatest('async', incrementAsync)
])
}
let sagaMiddleware = createSagaMiddleware();
let store = createStore(rootReducer, applyMiddleware(sagaMiddleware))
sagaMiddleware.run(rootSaga);
store.dispatch({ type: 'hello' });
store.dispatch({ type: 'async' });
支持异步的还有redux-promise 等
React从入门到放弃之前奏(4):Redux中间件的更多相关文章
- React从入门到放弃之前奏(5):ReactRouter4
概念 安装:npm i -S react-router react-router-dom GitHub:ReactTraining/react-router React Router中有三种类型的组件 ...
- React从入门到放弃之前奏(1):webpack4简介
接触webpack是好久之前的事情了,最近看了下webpack没想到都到4了. webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler). 会创建1个 ...
- React从入门到放弃之前奏(2):React简介
本系列将尽可能使用ES6(ES2015)语法.所以均在上节webpack的基础上做开发. React是Facebook开发的一款JS库,因为基于Virtual DOM,所以响应速度快,以及支持跨平台. ...
- React从入门到放弃之前奏(3):Redux简介
安装 npm i -S redux react-redux redux-devtools 概念 在redux中分为3个对象:Action.Reducer.Store Action 对行为(如用户行为) ...
- Scrapy入门到放弃04:下载器中间件,让爬虫更完美
前言 MiddleWare,顾名思义,中间件.主要处理请求(例如添加代理IP.添加请求头等)和处理响应 本篇文章主要讲述下载器中间件的概念,以及如何使用中间件和自定义中间件. MiddleWare分类 ...
- 在 2016 年学 JavaScript 是一种什么样的体验?(React从入门到放弃)
jquery 年代 vs 前端模块化 http://blog.csdn.net/offbye/article/details/52793921 ++ 嘿,我最近接到一个 Web 项目,不过老实说,我这 ...
- D3.js从入门到“放弃”指南
前言 近期略有点诸事不顺,趁略有闲余之时,玩起D3.js.之前实际项目中主要是用各种chart如hightchart.echarts等,这些图形库玩起来貌都是完美的,一切皆可配置,但几年前接触了D3之 ...
- 一天带你入门到放弃vue.js(一)
写在前面的话! 每个新的框架入手都会进行一些列的扯犊子!这里不多说那么多!简简单单说一下vue吧! Vue.js是目前三大框架(angular,vue,react)之一,是渐进式js框架,据说是摒弃了 ...
- 小白学 Python 爬虫(28):自动化测试框架 Selenium 从入门到放弃(下)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
随机推荐
- unix命令自我总结
三种参数类型 1⃣时间日期: cal times time 2⃣文字处理: ctl+v 输入控制字符 ${#str} str字符串长度 expr length $abc 同上 typeset -i x ...
- ruby轻松自删除代码
因为windows的文件删除机制和unix like的不一样,so不保证如下代码能在windows中使用,哪位童鞋帮我在windows中测试一下也好啊! #!/usr/bin/ruby 5.times ...
- 基于event 实现的线程安全的优先队列(python实现)
event 事件是个很不错的线程同步,以及线程通信的机制,在python的许多源代码中都基于event实现了很多的线程安全,支持并发,线程通信的库 对于优先队列的堆实现,请看<python下实现 ...
- Java内存模型_volatile
volatile变量自身具有下列两点特性: 可见性:锁的happens-before规则保证释放锁和获取锁的两个线程之间的内存可见性.意味着对一个volatile变量的读,总是能看到(任意线程)对这个 ...
- 使用IntelliJ IDEA的小技巧快乐编程(2)
前言 本篇介绍的技巧为IntelliJ IDEA中自动代码生成相关的技巧,合理的使用这些技巧将大大提高的你的编码效率 :) Trick 6. 使用模板代码 idea默认的提供了许多模板代码,你可以使用 ...
- 【也许CTO并不是终点开篇】CTO也只不过是CTO罢了
不想做将军的士兵不是好士兵,这句话可以有很功利的理解方式,对应到我们自己很可能是:不想做CTO的程序员不是好程序员!几年前对这句话的理解与现在有很多不同,因为我现在已经是一名中小型公司的CTO了,这句 ...
- 想要薪资20-30K,Python程序员认真敲代码就够了!
在这个年代,互联网的飞速壮大大家有目共睹,除了表露出的公共受益,其中计算机编程者也是做出了巨大的贡献,即使外国编程语言仍旧属于领导者,但是在互联网的壮大下,我们这是"地球村",国内 ...
- CSS学习笔记3:选择器及优先级
CSS选择器的类型: 标签选择器 类选择器 ID选择器 全局选择器 群组选择器 后代选择器 1.标签选择器: 以HTML的标签作为选择器,凡是选择了一个标签,那么所有这个标签的内容都是用了 ...
- Java学习导航
由于最近在系统的重新学习Java,为了便于日后复习,给个人博客中Java内容做一个目录. Java基础:Java虚拟机(JVM) Java基础:内存模型 Java基础:JVM垃圾回收算法 Java基础 ...
- AVL Tree 操作
1.AVL树是带有平衡条件的二叉查找树, 一棵AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树. 2.AVL树的删除要比插入复杂.如果删除相对较少,那么用懒惰删除的方法是最好的策略. 3 ...