react中间件是什么?
理解了中间件以后,就可以处理异步操作了。
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import reducer from './reducers'; // Note: this API requires redux@>=3.1.0 const store = createStore( reducer, applyMiddleware(thunk) );上面代码使用redux-thunk中间件,改造store.dispatch,使得后者可以接受函数作为参数。
五、redux-thunk 中间件异步操作至少要送出两个 Action:用户触发第一个 Action,这个跟同步操作一样,没有问题;如何才能在操作结束时,系统自动送出第二个 Action 呢?
看一下redux-promise的源码,就会明白它内部是怎么操作的。
let next = store.dispatch; store.dispatch = function dispatchAndLog(action) { console.log('dispatching', action); next(action); console.log('next state', store.getState()); }上面代码中,对store.dispatch进行了重定义,在发送 Action 前后添加了打印功能。这就是中间件的雏形。
操作开始时,送出一个 Action,触发 State 更新为"正在操作"状态,View 重新渲染
export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer); var dispatch = store.dispatch; var chain = []; var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) }; chain = middlewares.map(middleware => middleware(middlewareAPI)); dispatch = compose(...chain)(store.dispatch); return {...store, dispatch} } }上面代码中,所有中间件被放进了一个数组chain,然后嵌套执行,最后执行store.dispatch。可以看到,中间件内部(middlewareAPI)可以拿到getState和dispatch这两个方法。
操作发起时的 Action
奥妙就在 Action Creator 之中。
(2)返回的函数的参数是dispatch和getState这两个 Redux 方法,普通的 Action Creator 的参数是 Action 的内容。
在react中,中间件就是一个函数,对store.dispatch方法进行了改造,在发出Action和执行Reducer这两步之间,添加了其他功能;常用的中间件都有现成的,只要引用别人写好的模块即可。
(1)fetchPosts返回了一个函数,而普通的 Action Creator 默认返回一个对象。
(3)在返回的函数之中,先发出一个 Action(requestPosts(postTitle)),表示操作开始。
同步操作只要发出一种 Action 即可,异步操作的差别是它要发出三种 Action。
它是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行。下面是它的源码。
操作失败时的 Action
这样的处理,就解决了自动发送第二个 Action 的问题。但是,又带来了一个新的问题,Action 是由store.dispatch方法发送的。而store.dispatch方法正常情况下,参数只能是对象,不能是函数。

上面代码中,redux-logger提供一个生成器createLogger,可以生成日志中间件logger。然后,将它放在applyMiddleware方法之中,传入createStore方法,就完成了store.dispatch()的功能增强。
const store = createStore( reducer, applyMiddleware(thunk, promise, logger) );上面代码中,applyMiddleware方法的三个参数,就是三个中间件。有的中间件有次序要求,使用前要查一下文档。比如,logger就一定要放在最后,否则输出结果会不正确。
操作结束后,再送出一个 Action,触发 State 更新为"操作结束"状态,View 再一次重新渲染
(3)Action:存放数据的对象,即消息的载体,只能被别人操作,自己不能进行任何操作。
这就需要使用redux-promise中间件。
上面代码中,有几个地方需要注意。
(4)异步操作结束之后,再发出一个 Action(receivePosts(postTitle, json)),表示操作结束。
const fetchPosts = postTitle => (dispatch, getState) => { dispatch(requestPosts(postTitle)); return fetch(`/some/API/${postTitle}.json`) .then(response => response.json()) .then(json => dispatch(receivePosts(postTitle, json))); }; }; // 使用方法一 store.dispatch(fetchPosts('reactjs')); // 使用方法二 store.dispatch(fetchPosts('reactjs')).then(() => console.log(store.getState()) );上面代码中,fetchPosts是一个Action Creator(动作生成器),返回一个函数。这个函数执行后,先发出一个Action(requestPosts(postTitle)),然后进行异步操作。拿到结果后,先将结果转成 JSON 格式,然后再发出一个 Action( receivePosts(postTitle, json))。
以向服务器取出数据为例,三种 Action 可以有两种不同的写法。
一、中间件的概念为了理解中间件,让我们站在框架作者的角度思考问题:如果要添加功能,你会在哪个环节添加?
二、中间件的用法本教程不涉及如何编写中间件,因为常用的中间件都有现成的,只要引用别人写好的模块即可。比如,上一节的日志中间件,就有现成的redux-logger模块。这里只介绍怎么使用中间件。
这里有两点需要注意:
因此,异步操作的第一种解决方案就是,写出一个返回函数的 Action Creator,然后使用redux-thunk中间件改造store.dispatch。
let state = { // ... isFetching: true, didInvalidate: true, lastUpdated: 'xxxxxxx' };上面代码中,State 的属性isFetching表示是否在抓取数据。didInvalidate表示数据是否过时,lastUpdated表示上一次更新时间。
中间件就是一个函数,对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。常用的中间件都有现成的,只要引用别人写好的模块即可。
(1)Reducer:纯函数,只承担计算 State 的功能,不合适承担其他功能,也承担不了,因为理论上,纯函数不能进行读写操作。
import { createAction } from 'redux-actions'; class AsyncApp extends Component { componentDidMount() { const { dispatch, selectedPost } = this.props // 发出同步 Action dispatch(requestPosts(selectedPost)); // 发出异步 Action dispatch(createAction( 'FETCH_POSTS', fetch(`/some/API/${postTitle}.json`) .then(response => response.json()) )); }上面代码中,第二个dispatch方法发出的是异步 Action,只有等到操作结束,这个 Action 才会实际发出。注意,createAction的第二个参数必须是一个 Promise 对象。
三、applyMiddlewares()看到这里,你可能会问,applyMiddlewares这个方法到底是干什么的?
const fetchPosts = (dispatch, postTitle) => new Promise(function (resolve, reject) { dispatch(requestPosts(postTitle)); return fetch(`/some/API/${postTitle}.json`) .then(response => { type: 'FETCH_POSTS', payload: response.json() }); });写法二,Action 对象的payload属性是一个 Promise 对象。这需要从redux-actions模块引入createAction方法,并且写法也要变成下面这样。
(1)createStore方法可以接受整个应用的初始状态作为参数,那样的话,applyMiddleware就是第三个参数了。
import { createStore, applyMiddleware } from 'redux'; import promiseMiddleware from 'redux-promise'; import reducer from './reducers'; const store = createStore( reducer, applyMiddleware(promiseMiddleware) );这个中间件使得store.dispatch方法可以接受 Promise 对象作为参数。这时,Action Creator 有两种写法。写法一,返回值是一个 Promise 对象。
六、redux-promise 中间件既然 Action Creator 可以返回函数,当然也可以返回其他值。另一种异步操作的解决方案,就是让 Action Creator 返回一个 Promise 对象。
现在,整个异步操作的思路就很清楚了。
下面就是fetchPosts的代码,关键之处就在里面。

除了 Action 种类不同,异步操作的 State 也要进行改造,反映不同的操作状态。下面是 State 的一个例子。
const store = createStore( reducer, initial_state, applyMiddleware(logger) );(2)中间件的次序有讲究。
这时,就要使用中间件redux-thunk。
操作成功时的 Action
export default function promiseMiddleware({ dispatch }) { return next => action => { if (!isFSA(action)) { return isPromise(action) ? action.then(dispatch) : next(action); } return isPromise(action.payload) ? action.payload.then( result => dispatch({ ...action, payload: result }), error => { dispatch({ ...action, payload: error, error: true }); return Promise.reject(error); } ) : next(action); }; }从上面代码可以看出,如果 Action 本身是一个 Promise,它 resolve 以后的值应该是一个 Action 对象,会被dispatch方法送出(action.then(dispatch)),但 reject 以后不会有任何动作;如果 Action 对象的payload属性是一个 Promise 对象,那么无论 resolve 和 reject,dispatch方法都会发出 Action。
以上就是react中间件是什么?的详细内容,更多请关注聚合云库其它相关文章!
想来想去,只有发送 Action 的这个步骤,即store.dispatch()方法,可以添加功能。举例来说,要添加日志功能,把 Action 和 State 打印出来,可以对store.dispatch进行如下改造。
(2)View:与 State 一一对应,可以看作 State 的视觉层,也不合适承担其他功能。
class AsyncApp extends Component { componentDidMount() { const { dispatch, selectedPost } = this.props dispatch(fetchPosts(selectedPost)) } // ...上面代码是一个异步组件的例子。加载成功后(componentDidMount方法),它送出了(dispatch方法)一个 Action,向服务器要求数据 fetchPosts(selectedSubreddit)。这里的fetchPosts就是 Action Creator。
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://www.juheyunku.com/jiaob/javascript/6511.shtml
相关文章
热门TAG
服务器 命令 技巧 详解 调用 标签 功能 织梦 javascript dedecms修改内容 织梦教程 php 白帽 企业网站 外链 权重 MYSQL 网站流量 实例解析 JSP 网站收录 搜索引擎 蜘蛛 windows jquery jquery教程 python tags标签 HTML 织梦cms最新文章
-
Javascript是什么?
时间:2021-01-04
-
Canvas入门实战之实现一个
时间:2021-01-04
-
11月份GitHub上最热门的Ja
时间:2021-01-04
-
一篇带给你JavaScript的Cla
时间:2021-01-04
-
详解js异步文件加载器
时间:2021-01-04
-
深入理解JavaScript中的箭头
时间:2021-01-04
-
复盘Node项目中遇到的13+常
时间:2021-01-04
-
连续3年稳居第一,全球
时间:2021-01-04
热门文章
-
连续3年稳居第一,全球1240万用户,Java
时间:2021-01-04
-
一篇带给你JavaScript的Class语法介绍
时间:2021-01-04
-
深入理解JavaScript中的箭头函数
时间:2021-01-04
-
Javascript在Chrome浏览器中调试的七个步骤
时间:2021-01-04
-
Canvas入门实战之实现一个图形验证码
时间:2021-01-04
-
详解js异步文件加载器
时间:2021-01-04
-
复盘Node项目中遇到的13+常见问题和解决方
时间:2021-01-04
-
11月份GitHub上最热门的JavaScript开源项目
时间:2021-01-04
-
Javascript是什么?
时间:2021-01-04
