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 => {}

异步操作

  1. 同步操作只要发出一种 Action 即可,异步操作通常需要发出多种 Action(开始、成功、失败)
  2. 异步操作有2种Action写法(3种type 或者 添加erro 和 response字段)
  3. 异步操作的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'// 上次更新时间
};

使用中间件

  1. 使用createStore(reducer, enhancer)createStore(reducer, preloadedState, enhancer)
  2. 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中间件的更多相关文章

  1. React从入门到放弃之前奏(5):ReactRouter4

    概念 安装:npm i -S react-router react-router-dom GitHub:ReactTraining/react-router React Router中有三种类型的组件 ...

  2. React从入门到放弃之前奏(1):webpack4简介

    接触webpack是好久之前的事情了,最近看了下webpack没想到都到4了. webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler). 会创建1个 ...

  3. React从入门到放弃之前奏(2):React简介

    本系列将尽可能使用ES6(ES2015)语法.所以均在上节webpack的基础上做开发. React是Facebook开发的一款JS库,因为基于Virtual DOM,所以响应速度快,以及支持跨平台. ...

  4. React从入门到放弃之前奏(3):Redux简介

    安装 npm i -S redux react-redux redux-devtools 概念 在redux中分为3个对象:Action.Reducer.Store Action 对行为(如用户行为) ...

  5. Scrapy入门到放弃04:下载器中间件,让爬虫更完美

    前言 MiddleWare,顾名思义,中间件.主要处理请求(例如添加代理IP.添加请求头等)和处理响应 本篇文章主要讲述下载器中间件的概念,以及如何使用中间件和自定义中间件. MiddleWare分类 ...

  6. 在 2016 年学 JavaScript 是一种什么样的体验?(React从入门到放弃)

    jquery 年代 vs 前端模块化 http://blog.csdn.net/offbye/article/details/52793921 ++ 嘿,我最近接到一个 Web 项目,不过老实说,我这 ...

  7. D3.js从入门到“放弃”指南

    前言 近期略有点诸事不顺,趁略有闲余之时,玩起D3.js.之前实际项目中主要是用各种chart如hightchart.echarts等,这些图形库玩起来貌都是完美的,一切皆可配置,但几年前接触了D3之 ...

  8. 一天带你入门到放弃vue.js(一)

    写在前面的话! 每个新的框架入手都会进行一些列的扯犊子!这里不多说那么多!简简单单说一下vue吧! Vue.js是目前三大框架(angular,vue,react)之一,是渐进式js框架,据说是摒弃了 ...

  9. 小白学 Python 爬虫(28):自动化测试框架 Selenium 从入门到放弃(下)

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

随机推荐

  1. 用js来实现那些数据结构14(树02-AVL树)

    在使用二叉搜索树的时候会出现 一个问题,就是树的一条分支会有很多层,而其他的分支却只有几层,就像下面这样: 如果数据量够大,那么我们在某条边上进行增删改查的操作时,就会消耗大量的时间.我们花费精力去构 ...

  2. 【转载】tomcat+nginx+redis实现均衡负载、session共享(二)

    今天我们接着说上次还没完成session共享的部分,还没看过上一篇的朋友可以先看下上次内容,http://www.cnblogs.com/zhrxidian/p/5432886.html. 1.red ...

  3. [转]用python 10min手写一个简易的实时内存监控系统

    简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star 腾讯视频链接 ...

  4. Eclipse下无法编译,或者WEB-INF/classes目录下没文件,编译失败的解决办法

    1. 确保 project->build automatically 已经被选上. 2. 如果选上了,也不好使, 使用这一招: project->clean..->选第2个clean ...

  5. 【已解决】C#中往SQLServer插入数据时遇到BUG

    错误信息如下: “System.Data.SqlClient.SqlException”类型的未经处理的异常在 System.Data.dll 中发生 其他信息: “”附近有语法错误. 文字版代码如下 ...

  6. 统一流控服务开源-1:场景&业界做法&算法篇

    最近团队在搞流量安全控制,为了应对不断增大的流量安全风险.Waf防护能做一下接入端的拦截,但是实际流量会打到整个分布式系统的每一环:Nginx.API网关.RPC服务.MQ消息应用中心.数据库.瞬间的 ...

  7. IntelliJ IDEA maven 构建简单springmvc项目

    环境: apache-tomcat-8.5.15 jdk1.8.0_172 IDEA 建立一个maven-webapp项目:Create New Project 后点击next 然后next 可以选择 ...

  8. PAT1124:Raffle for Weibo Followers

    1124. Raffle for Weibo Followers (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN ...

  9. @ConditionalOnMissingBean注解理解

    @ConditionalOnMissingBean注解作用在@bean定义上,它的作用就是在容器加载它作用的bean时,检查容器中是否存在目标类型(ConditionalOnMissingBean注解 ...

  10. linux几种时间函数总结

    一.linux时间函数总结 最近的工作中用到的时间函数比较频繁,今天抽时间总结一下,在linux下,常用的获取时间的函数有如下几个:  asctime,  ctime, gmtime, localti ...