简单介绍react redux的中间件的使用


Posted in Javascript onApril 06, 2018

用过react的同学都知道在redux的存在,redux就是一种前端用来存储数据的仓库,并对改仓库进行增删改查操作的一种框架,它不仅仅适用于react,也使用于其他前端框架。研究过redux源码的人都觉得该源码很精妙,而本博文就针对redux中对中间件的处理进行介绍。

在讲redux中间件之前,先用两张图来大致介绍一下redux的基本原理:

简单介绍react redux的中间件的使用

图中就是redux的基本流程,这里就不细说。

一般在react中不仅仅利用redux,还利用到react-redux:

简单介绍react redux的中间件的使用

react-redux这里也不细说。

redux中间件

一般情况下,redux是不具备处理异步请求的能力,稚嫩沟通过间接或者添加中间件的方式,加强了对dispatch的能力,是的redux具备异步的能力;

一般来说,redux处理异步的方式有两种:间接方式和中间件方式;

间接方式:

间接方式就死自定义异步的行为,保留dispatch同步的功能。
思路:就是讲异步返回的结果塞进action中,然后在通过dispatch同步到reduce中,再改变state;

简单介绍react redux的中间件的使用

demo:

request.get(API)
    .then(d => {
      store.dispatch(type: xxx, playload: d)
    })

这种方式没有破坏dispatch的同步机制,原汁原味的使用dispatch将数据同步到state中,但不好的地方就是每次调用都会写很长的一段。

中间件方式

中间件方式中核心部分就是redux提供的applyMiddleWare这个高阶函数,它通过多层调用后悔返回一个全新的store对象,全新的store对象和原来对象中,唯一的不同就是dispatch具备了异步的功能;

源码:

const applyMiddleWare = (...middlewares) => createStore => (reducer, initState) =>{
  const store = createStore(reducer, initState);
  const _dispatch = store.dispatch;
  const MiddleWareAPI = {
    getState: store.getState,
    dispatch: action => _dispatch(action)  1)
  };
  const chain = [];
  chain = middlewares.map(middleware => {middleware(MiddleWareAPI)}); 2)
  let dispatch = compose(...chain)(store.dispatch);  3)
  return {
    dispatch,
    ...store
  }
}

短短十几行代码,其中却蕴含着不少精妙之处,博主选择了其中三处地方进行分析其精妙之处:

1)MiddleWareAPI主要是通过塞进中间件,从而最终塞进action中,让action能具备dispatch的能力,而这里为什么要用匿名函数,主要原因是因为要让MiddleWareAPI.dispatch中的store和applyMiddleWare最终返回的store保持一致,要注意的是MiddleWareAPI.dispatch不是真正让state改变,它可以理解为是action和中间件的一个桥梁。

2)改地方就是将MiddleWareAPI塞进所有的中间件中,然后返回一个函数,而中间件的形式后面会说到。

3)该地方是最为精妙之处,compose会将chain数组从右到左一次地柜注入到前一个中间件,而store.dispatch会注入到最右边的一个的中间件。其实这里可以将compose理解为reduce函数。

eg:

M = [M1,M2,M3] ----> M1(M2(M3(store.dispatch)));

从这里其实就知道中间件大致是什么样子的了:

中间件基本形式:

const MiddleWare = store => next => action => {
  ...
}

参数解释:

  1. store:其实就是MiddleWareAPI;
  2. next: 这里有两种情况,如果改中间件是在middlewares数组里最右边,则next就是store.dispatch;否则就是它相邻左边的一个中间件返回值(闭包函数,就是action => {}这个函数);
  3. action:可以是函数,也可以是含有promise的对象;

到这里可能会有些糊涂,糊涂的地方可能就是next和store.dispatch的区别分不清;

区别:

next(最右边的中间件):其实是真正触发reducer,改变state的dispatch,这里的dispatch和state是同步关系的;这里的action必须是一个对象,不能含有异步信息;

next(非最右边的中间件):其实就是相邻前一个中间件返回的函数(action => {...});这里的action就是上一级中间件next(action)中的action,第一个中间件的action就是项目中store.dispatch(action)中的action。

中间件中的store.dispatch:其实就是用来塞进action的,这里就理解为action和中间件通信的渠道吧。

流程图:

简单介绍react redux的中间件的使用

demo:

export const MiddleForTest = store => next => action => {
  if (typeof action === 'function') {
    action(store);
  } else {
    next(action);
  }
};

export const MiddleForTestTwo = store => next => action => {
  next(action);
};

export function AjaxAction(store) {
  setTimeout(function () {
    store.dispatch({
      type: 'up',
      playload: '异步信息'
    })
  }, 1000)
}

store.dispatch(AjaxAction);

说道这里应该会对中间件有个大致的认识,接下来介绍一下常用的中间件以及自己写一个中间件。

redux-thunk:主要是适用于action是一个函数的情况,它是对原有的中间件模式再封装多一层,原则上是支持promise为主的action函数;

export function AjaxThunk (url, type) {
  return dispatch => {
    Ajax(url)
      .then(d => {
        dispatch({
          type,
          playload: d
        })
      })
  }
}
store.dispatch(AjaxThunk(url1, 'add'));

redux-promise:主要就是针对action对象,action对象是一个promise的异步请求函数:

它的大概实现思路是:

const promiseAction = store => next => action => {
    const {type, playload} = action;
    if (playload && typeof playload.then === 'function') {
      playload.then(result => {
        store.dispatch({type, playload: result});
      }).catch(e => {})
    } else {
      next(action);
    }
}

action = {
 type: 'xxx',
 playload: Ajax(url)
}

自定义中间件:很多时候网上的redux中间件可能不太符合项目中的需要,所以这时候可以自己写一套适合项目的中间件,以下指示本博主的一个demo,形式不唯一:

export const PromiseWares = store => next => action => {
  next({type: 'right', playload: 'loading'});
  if (typeof action === 'function') {
    const {dispatch} = store;
    action(dispatch);
  } else {
    const {type, playload} = action;
    if (playload && typeof playload.then === 'function') {
      playload.then(result => {
        store.dispatch({type, playload: result});
      }).catch(e => {})
    } else {
      next(action);
      next({type: 'right', playload: 'noLoading'});
    }
  }
};

以上就是本博主对redux中间件的理解,如有不对,请指出。

Javascript 相关文章推荐
Javascript 继承机制的实现
Aug 12 Javascript
JavaScript中的this关键字介绍与使用实例
Jun 21 Javascript
不使用浏览器运行javascript代码的方法
Jul 24 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 语法
Jan 09 Javascript
javascript运算符——位运算符全面介绍
Jul 14 Javascript
浅谈Angularjs link和compile的使用区别
Oct 21 Javascript
JS创建Tag标签的方法详解
Jun 09 Javascript
Angular4实现图片上传预览路径不安全的问题解决
Dec 25 Javascript
利用Vue2.x开发实现JSON树的方法
Jan 04 Javascript
js运算符的一些特殊用法
Jul 29 Javascript
微信小程序使用Vant Weapp组件库的方法步骤
Aug 01 Javascript
vue 解除鼠标的监听事件的方法
Nov 13 Javascript
webpack源码之loader机制详解
Apr 06 #Javascript
vue.js项目nginx部署教程
Apr 05 #Javascript
常用的 JS 排序算法 整理版
Apr 05 #Javascript
通过 JS 判断页面是否有滚动条的实现方法
Apr 05 #Javascript
mint-ui在vue中的使用示例
Apr 05 #Javascript
webpack热模块替换(HMR)/热更新的方法
Apr 05 #Javascript
详解Vue基于 Nuxt.js 实现服务端渲染(SSR)
Apr 05 #Javascript
You might like
防止用户利用PHP代码DOS造成用光网络带宽
2011/03/01 PHP
php中json_decode()和json_encode()的使用方法
2012/06/04 PHP
Linux操作系统安装LAMP环境
2015/06/26 PHP
简单的自定义php模板引擎
2016/08/26 PHP
Nginx环境下PHP flush失效的解决方法
2016/10/19 PHP
老生常谈PHP面向对象之命令模式(必看篇)
2017/05/24 PHP
PHP基于自定义类随机生成姓名的方法示例
2017/08/05 PHP
kindeditor 加入七牛云上传的实例讲解
2017/11/12 PHP
用js判断浏览器是否是IE的比较好的办法
2007/05/08 Javascript
javascript查找字符串中出现最多的字符和次数的小例子
2013/10/29 Javascript
使用AngularJS实现表单向导的方法
2015/06/19 Javascript
两种JS实现屏蔽鼠标右键的方法
2020/08/20 Javascript
js实现Form栏显示全格式时间时钟效果代码
2015/08/19 Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
2018/09/12 Javascript
vue实现PC端录音功能的实例代码
2019/06/05 Javascript
使用Layui搭建后台管理界面的操作方法
2019/09/20 Javascript
js 执行上下文和作用域的相关总结
2021/02/08 Javascript
Python中import机制详解
2017/11/14 Python
python 设置文件编码格式的实现方法
2017/12/21 Python
python写入并获取剪切板内容的实例
2018/05/31 Python
Python之dict(或对象)与json之间的互相转化实例
2018/06/05 Python
Python基于聚类算法实现密度聚类(DBSCAN)计算【测试可用】
2018/12/26 Python
python3 BeautifulSoup模块使用字典的方法抓取a标签内的数据示例
2019/11/28 Python
在django中使用apscheduler 执行计划任务的实现方法
2020/02/11 Python
实现ECharts双Y轴左右刻度线一致的例子
2020/05/16 Python
使用keras2.0 将Merge层改为函数式
2020/05/23 Python
世界领先的26岁以下学生和青少年旅行预订网站:StudentUniverse
2018/07/01 全球购物
奥地利智能家居和智能生活网上商店:tink.at
2019/10/07 全球购物
幼儿园教师备课制度
2014/01/12 职场文书
护理专业自荐信范文
2014/02/26 职场文书
政府门卫岗位职责
2014/04/29 职场文书
清明节演讲稿
2014/05/27 职场文书
小学生安全教育广播稿
2014/10/20 职场文书
功夫熊猫观后感
2015/06/10 职场文书
Python实现日志实时监测的示例详解
2022/04/06 Python
Linux下使用C语言代码搭建一个简单的HTTP服务器
2022/04/13 Servers