Redux中间件,其实就是一个函数, 当我们发送一个action的时候,先经过它,我们就可以对action进行处理,然后再发送action到达reducer, 改变状态,这时我们就可以在中间件中,对action 和对应的state进行跟踪,有利于bug处理,还有就是利用中间件进行异步处理。中间件的由来在Redux官网上已经解释的很清楚了,我们这里只是使用它们。

  Redux 中间件的样式如下:

const logger = store => next => action => {// 这里面就是我们这个中间件的要做的事件,由于把store, action 都传入来进来,我们可以对action进行操作,也可以调用store暴露的 api.
}

  它接受一个store作为参数,然后返回一个函数,函数接受next作为参数,还是返回一个函数,函数再接受一个参数action, 然后,我们在这个函数体内写代码,表示这个中间件要做的事情,es6的箭头函数可能不直观,我们用es5重写一下,就以官网中的logger为例

// es6 箭头函数样式
const logger = store => next => action => {console.log('dispatching', action);let result = next(action);console.log('next state', store.getState());return result;
}
// es5 普通样式
const logger = function(store) {return function(next) {return function(action) {console.log('dispatching', action);let result = next(action);console.log('next state', store.getState());return result;}}
}

  在这个logger中间件(函数)中,第一句console.log(),输出我们发送的action, 从而记录下action. 第二句next, 调用next 函数发送action, 这个next函数,就是store.dispath() 方法的封装。next就是store.dispatch action后,我们就会获取的新的状态,所以第三句console.log (store.getState())就可以获取新的状态并记录。最后一句return, 主要的是因为中间件可以链接起来调用,一个接一个,所以要return, 把它传入到下一个中间件。

  新建一个项目来体验一下中间件。由于后面还要使用异步,我们就一起写了。项目非常简单,页面上有一个按钮,点击按钮时,我们从randomuser.me网站上随机获取一个用户,并进行展示,这很明显涉及到了异步请求。 直接把redux介绍中的使用npm和ES6的项目复制过来,index.html中的body修改如下:

<body><div class="container"><button class='btn btn-blue' id="getUser">New Random User</button>      <h2 id="status"></h2>       <h2 id="name"></h2><h2 id="email"></h2><h2 id="gender"></h2></div><script src='./bundle.js'></script></body>

  counter.css 修改如下:

body {padding: 40px;font-family: "helvetica neue", sans-serif;}.container {width: 600px;margin: auto;color: black;padding: 20px;text-align: center;
}.container h1 {margin: 0;padding: 20px;font-size: 48px;
}.container .btn {border: 0;padding: 15px;margin: 10px;width: 40%;font-size: 15px;outline: none;border-radius: 3px;color: #FFF;font-weight: bold;
}.btn.btn-blue {background-color: #55acee;box-shadow: 0px 5px 0px 0px #3C93D5;
}
.pending {color: #55acee;
}.error {color: #d84a4a;
}.success {color: #2ecc71;
}

  npm run dev 启动项目后,我们页面中就只有一个按钮

  现在写index.js文件,首先我们要定义state, reducer来创建store. 对于异步请求来说,它至少有3种状态,请求中的状态,请求成功时的状态,请求失败时的状态。所以首先我们要记录这个状态成用户提示,为了成功和失败进行样式区分,还有一个样式状态,成功之后,我们获取到用户的信息,所以要有一个user信息。

// state 状态
const initalState = {user: {        // 记录个人信息,每个人都有姓名,年龄,邮箱,所以它是一个对象。name: '',email: '',gender: ''},status: '',     // 记录请求状态。 statusClass: '' // 请求状态成功或失败的样式标识
}

  对于三种状态,它肯定会有三个action进行对应,请求中的状态,我们可以发送一个 GET_USER, 请求成功的状态,我们可以发送USER_RECIEVED, 请求失败的状态,我们可以发送ERROR,相应地,recuder中就要处理这3个type

  当我们发送GET_USER action时,那么请求状态的变量status应为pending, 同是statusClass至为pending ,所以reducer这个分支,只需要要改变这个状态为{user:{}, status: 'pending', statusClass: 'pending"}

  当USER_RECIEVED 时,我们就获取的user信息,同时state 就变成了 User Recieved 状态,这个分支可能如下:

{user: {       name: 'sam',email: '105@gmail.com',gender: 'male'},status: 'User reciever',     statusClass: 'success'
}

  当ERROR 时,我们也是改变状态,就可以了,和GET_USER  一样。整 个reducer代码如下:

// REDCUER
function userReducer(state=initalState, action) {const user = {name: '',email: '',gender: ''};switch (action.type) {case 'GET_USER':return {...state, status: 'Pending...', statusClass: 'pending'}case 'USER_RECIEVED':user.name = `${action.payload[0].name.first} ${action.payload[0].name.last}`user.email = action.payload[0].email;user.gender = action.payload[0].gender;return {...state, user, status: 'User Recieved', statusClass: 'success'}case 'ERROR':return {...state, status: `${action.payload.message}`, statusClass: 'error'}default:return state}
}

   这时我们就可以创建store了,创建store的时候,它可以接受第二个参数,就是中间件,不过要用到Redux提件的

applyMiddleware 函数,所有用到的中间件依次作为参数,传递给它,这时使用一下logger
// STORE接受applyMiddlerWare 参数,从而使用中间件,把用到的中间件传入到applyMiddlerWare函数中
const store = createStore(userReducer, applyMiddleware(logger));

  这时我们点击按钮发送一个 GET_USER试一试

// ACTIONS
document.getElementById('getUser').addEventListener('click', function () {store.dispatch({type:"GET_USER"});
})

  可以看到控制台上对我们的action 和state 进行的记录, 中间件起了作用。

  对于logger这种常用的中间件,网上已经有第三方库了,就是redux-logger. npm install redux-logger --save 安装到我们的项目中, 然后在index.js文件引入,import {createLogger} from 'redux-logger'; 然后applyMiddleware(createLogger()) 就可以了。

  现在再做异步请求, 有两个中间件可以做异步action:redux-thunk 和redux-promise, 先使用redux-thunk, 发送异步请求用到了 axios;  npm install redux-thunk axios --save 安装它们。

  使用thunk做异步action, dispatch可以接受一个函数作为参数,这个函数接受dispatch作为参数,在这个函数内部我们可以发送异步请求,获取结果后,再发送action

// 使用异步ACTIONS
document.getElementById('getUser').addEventListener('click', function () {store.dispatch(dispatch => {// 请求中的actiondispatch({type: 'GET_USER'});// do the xhr requestaxios.get('https://randomuser.me/api/')// 请求成功action.then(response => {dispatch({type: 'USER_RECIEVED', payload: response.data.results})})// 失败的action.catch(error => {dispatch({ type: 'ERROR', payload: error})})});})

  最后写一个render函数,把获取到的状态渲染到页面上

  

// 获取元素
const nameEl = document.getElementById('name');
const emailEl = document.getElementById('email');
const genderEl = document.getElementById('gender');
const statusEl = document.getElementById('status');function render() {const state = store.getState()nameEl.innerHTML = state.user.name;emailEl.innerHTML = state.user.email;genderEl.innerHTML = state.user.gender;statusEl.innerHTML = state.status;statusEl.className = state.statusClass;
}render()
store.subscribe(render)

  整 个index.js文件如下:

import { createStore, applyMiddleware } from 'redux';  // 引入applyMiddleware 使用中间件
import {createLogger} from 'redux-logger';             // 使用第三方logger
import thunk from 'redux-thunk';                       // 使用redux-thunk 操作异步action
import axios from 'axios';                             // 使用axios发送异步请求// state 状态
const initalState = {user: {        // 记录个人信息,每个人都有姓名,年龄,邮箱,所以它是一个对象。name: '',email: '',gender: ''},status: '',     // 记录请求状态。 statusClass: '' // 请求状态
}// REDCUER
function userReducer(state=initalState, action) {const user = {name: '',email: '',gender: ''};switch (action.type) {case 'GET_USER':return {...state, status: 'Pending...', statusClass: 'pending'}break;case 'USER_RECIEVED':user.name = `${action.payload[0].name.first} ${action.payload[0].name.last}`user.email = action.payload[0].email;user.gender = action.payload[0].gender;return {...state, user, status: 'User Recieved', statusClass: 'success'}break;case 'ERROR':return {...state, status: `${action.payload.message}`, statusClass: 'error'}default:return state}
}// STORE, 使用了第三方 logger 和thunk中间件
const store = createStore(userReducer, applyMiddleware(createLogger(), thunk));
// 获取元素
const nameEl = document.getElementById('name');
const emailEl = document.getElementById('email');
const genderEl = document.getElementById('gender');
const statusEl = document.getElementById('status');// 进行渲染
function render() {const state = store.getState()nameEl.innerHTML = state.user.name;emailEl.innerHTML = state.user.email;genderEl.innerHTML = state.user.gender;statusEl.innerHTML = state.status;statusEl.className = state.statusClass;
}render()
store.subscribe(render)// 使用异步ACTIONS
document.getElementById('getUser').addEventListener('click', function () {store.dispatch(dispatch => {// 请求中的actiondispatch({type: 'GET_USER'});// do the xhr requestaxios.get('https://randomuser.me/api/')// 请求成功action.then(response => {dispatch({type: 'USER_RECIEVED', payload: response.data.results})})// 失败的action.catch(error => {dispatch({ type: 'ERROR', payload: error})})});})

  当点击页面上的按钮时,先看到的pend..., 然后就是获取人物信息

    

  现在再使用redux-promise-middleware来发送异步action.  redux-promise-middleware中间件充分利用了promise的特性, 因为promise有三种状态,pending ,fullfilled, reject,  正好对应着异步请求的三种状态, 我们只要发送一个action, 自动会获取到三个action,把pending, fullfilled, reject加到我们发送的action 后面形成。npm install redux-promise-middleware --save 安装它,然后import promise from redux-promise-middleware引入。在异步action中我们只发送一个action, 比如FETCH_USER;

// 使用异步ACTIONS
document.getElementById('getUser').addEventListener('click', function () {store.dispatch({type: 'FETCH_USER',payload: axios.get("https://randomuser.me/api/")});
})

  虽然只有一个action,它实际上发送了三个action:  FETCH_USER_PENDING,  FETCH_USER_FULFILLED,  FETCH_USER_REJECTED,  你可以看到就是我们发送的action, 后面加上promise的三种状态形成: reducer修改如下:

// REDCUER
function userReducer(state=initalState, action) {const user = {name: '',email: '',gender: ''};switch (action.type) {case 'FETCH_USER_PENDING':return {...state, sendingRequest: true, status: 'Pending...', statusClass: 'pending'}break;case 'FETCH_USER_FULFILLED':user.name = `${action.payload.data.results[0].name.first} ${action.payload.data.results[0].name.last}`user.email = action.payload.data.results[0].email;user.gender = action.payload.data.results[0].gender;return {...state, sendingRequest: false, user, status: 'User Recieved', statusClass: 'success'}break;case 'FETCH_USER_REJECTED':return {...state, sendingRequest: false, status: `${action.payload.message}`, statusClass: 'error'}default:return state}
}

  现在点击按钮,也可以获取到用户信息。整个代码如下:

import { createStore, applyMiddleware } from 'redux';  // 引入applyMiddleware 使用中间件
import {createLogger} from 'redux-logger';             // 使用第三方logger
import promise from 'redux-promise-middleware';
import axios from 'axios';                             // 使用axios发送异步请求// state 状态
const initalState = {user: {        // 记录个人信息,每个人都有姓名,年龄,邮箱,所以它是一个对象。name: '',email: '',gender: ''},status: '',     // 记录请求状态。 statusClass: '' // 请求状态
}// REDCUER
function userReducer(state=initalState, action) {const user = {name: '',email: '',gender: ''};switch (action.type) {case 'FETCH_USER_PENDING':return {...state, sendingRequest: true, status: 'Pending...', statusClass: 'pending'}break;case 'FETCH_USER_FULFILLED':user.name = `${action.payload.data.results[0].name.first} ${action.payload.data.results[0].name.last}`user.email = action.payload.data.results[0].email;user.gender = action.payload.data.results[0].gender;return {...state, sendingRequest: false, user, status: 'User Recieved', statusClass: 'success'}break;case 'FETCH_USER_REJECTED':return {...state, sendingRequest: false, status: `${action.payload.message}`, statusClass: 'error'}default:return state}
}// STORE
const store = createStore(userReducer, applyMiddleware(createLogger(), promise()));
// 获取元素
const nameEl = document.getElementById('name');
const emailEl = document.getElementById('email');
const genderEl = document.getElementById('gender');
const statusEl = document.getElementById('status');// 进行渲染
function render() {const state = store.getState()nameEl.innerHTML = state.user.name;emailEl.innerHTML = state.user.email;genderEl.innerHTML = state.user.gender;statusEl.innerHTML = state.status;statusEl.className = state.statusClass;
}render()
store.subscribe(render)// 使用异步ACTIONS
document.getElementById('getUser').addEventListener('click', function () {store.dispatch({type: 'FETCH_USER',payload: axios.get("https://randomuser.me/api/")});
})

 

转载于:https://www.cnblogs.com/SamWeb/p/7899634.html

Redux学习(2) ----- 异步和中间件相关推荐

  1. [Redux/Mobx] Redux怎么添加新的中间件?

    [Redux/Mobx] Redux怎么添加新的中间件? applyMiddleware 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持一定很酷.欢迎大家一起讨论 主目录 与歌 ...

  2. Redux 学习总结 (React)

    在 React 的学习和开发中,如果 state (状态)变得复杂时(例如一个状态需要能够在多个 view 中使用和更新),使用 Redux 可以有效地管理 state,使 state tree 结构 ...

  3. redux学习笔记归纳

    设计思想: (1)Web 应用是一个状态机,视图与状态是一一对应的. (2)所有的状态,保存在一个对象里面. 核心源码: 基本概念:  1.Store:就是保存数据的地方,你可以把它看成一个容器.整个 ...

  4. Router+Redux学习总结

    一.React-Router配置路由 在实际应用中,我们不可能只有一页页面,切换页面需要通过Router配置,这样输入不同的url就能看到不同的页,或者点击不同的按钮可以在下方加载不同的组件. (说明 ...

  5. 前端综合学习笔记---异步、ES6/7、Module、Promise同步 vs 异步

    个人bolg地址 同步 vs 异步 先看下面的 demo,根据程序阅读起来表达的意思,应该是先打印100,1秒钟之后打印200,最后打印300.但是实际运行根本不是那么回事 console.log(1 ...

  6. Redux 学习之 middleware详解

    什么是middleware middleware翻译过来叫中间件,这是一个很抽象的名词,按我的理解的话:"中间"是个形容词,"件"应该是一个名词.那么我们重点关 ...

  7. 《强化学习周刊》第41期:MERLIN、分散式多智能体强化学习、异步强化学习

    No.41 智源社区 强化学习组 强 化 学  习 研究 观点 资源 活动 周刊订阅 告诉大家一个好消息,<强化学习周刊>已经开启"订阅功能",以后我们会向您自动推送最 ...

  8. Redux 学习笔记

    1:首先安装redux: npm install --save redux 2:引入redux : import { createStore } from 'redux'; //首先创建执行函数,Re ...

  9. Django 2.0 学习(20):Django 中间件详解

    Django 中间件详解 Django中间件 在Django中,中间件(middleware)其实就是一个类,在请求到来和结束后,Django会根据自己的规则在合适的时机执行中间件中相应的方法. 1. ...

最新文章

  1. 【Linux】linux使用mplayer播放摄像头
  2. 微软成功抵御峰值高达 2.4Tbps 的 DDoS 攻击
  3. 编码(人类与机器间的语言)中
  4. Glide @GlideModule 注解使用
  5. 那些年我们用过神级的代码注释
  6. aws terraform_如何使用Terraform通过Direct Connect扩展AWS基础架构
  7. Django项目中使用Redis
  8. 淘宝店铺所有商品API接口(店铺所有商品列表接口)
  9. 高效办公|用一套键鼠控制两台电脑解决方案
  10. 主键与其索引对应的关系
  11. 顺序表基本操作归纳整理
  12. Python学习视频收集
  13. 计算机组成原理学习笔记(3.存储系统 4.指令系统)
  14. Ubuntu 使用firefox插件下载百度云文件
  15. 【C++ Primer Plus】第14章 C++中的代码重用
  16. Unity通过鼠标或者手势实现拉进拉远,旋转等操作的常用方法
  17. [语录]足球解说员贺炜语录
  18. Read Committed
  19. Jmeter基础-配置原件
  20. vue关于element日历calendar组件上月、今天、下月、日历块点击事件

热门文章

  1. ExtJS4.2:自定义主题 入门
  2. Microsoft.Net框架程序设计学习笔记(11):类型构造器
  3. 加了try-catch也能自动定位到异常代码[VS Tips]
  4. 数据是互联网下半场产品人突围之道
  5. Putty常用属性设置
  6. Python Numpy 矩阵级基本操作(2)
  7. Node.js 极简入门Helloworld版服务器例子
  8. python django事务transaction源码分析
  9. 使用service实现登录、权限控制
  10. 微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...