用户发出 Action,Reducer 函数算出新的 State,View 重新渲染。但是,一个关键问题没有解决:异步操作怎么办?Action 发出以后,Reducer 立即算出 State,这叫做同步;Action 发出以后,过一段时间再执行 Reducer,这就是异步。
怎么才能 Reducer 在异步操作结束后自动执行呢?这就要用到新的工具:中间件(middleware)。
Github:https://github.com/gaearon/redux-thunk
一.redux-thunk
redux-thunk 是一个比较流行的 redux 异步 action 中间件,比如 action 中有 ****setTimeout**** 或者通过 ****fetch****通用远程 API 这些场景,那么久应该使用 redux-thunk 了。redux-thunk 帮助你统一了异步和同步 action 的调用方式,把异步过程放在 action 级别解决,对 component 没有影响。
1.中间件的概念
如果要添加功能,你会在哪个环节添加?
(1)Reducer:纯函数,只承担计算 State 的功能,不合适承担其他功能,也承担不了,因为理论上,纯函数不能进行读写操作。
(2)View:与 State 一一对应,可以看作 State 的视觉层,也不合适承担其他功能。
(3)Action:存放数据的对象,即消息的载体,只能被别人操作,自己不能进行任何操作。
想来想去,只有发送 Action 的这个步骤,即store.dispatch()方法,可以添加功能。举例来说,要添加日志功能,把 Action 和 State 打印出来,可以对store.dispatch进行如下改造。
let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
console.log('dispatching', action);
next(action);
console.log('next state', store.getState());
}
上面代码中,对store.dispatch进行了重定义,在发送 Action 前后添加了打印功能。这就是中间件的雏形。
中间件就是一个函数,对store.dispatch方法进行了改造,在发出 Action 和执行 Reducer 这两步之间,添加了其他功能。
二.使用
1.导入thunk: import thunk from 'redux-thunk'2.导入中间件: import {createStore,applyMiddleware} from 'redux'
3.创建store:let store = createStore(reducer函数,applyMiddleware(thunk))
4.激活redux-thunk中间件,只需要在createStore中加入applyMiddleware(thunk)就可以
5.创建action 创建函数,利用redux-thunk 帮助你统一了异步和同步 action 的调用方式(把异步过程放在 action 级别解决)
eg:
import { createStore ,applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
//1.新建store
const store = createStore(counter,applyMiddleware(thunk));
//action 创建函数 :延迟添加 拖俩天再给
export function addGunAsync(){
//thunk插件的作用,这里可以返回函数
return dispatch =>{
//异步结束后,手动执行dispatch
setTimeout(() => {
dispatch(addGUN())
}, 2000)
}
}
三.例子
从上一篇:Redux基本语法 机关枪的例子
这边补充异步的操作:
index.redux.js
//延迟添加 拖俩天再给
export function addGunAsync(){
//thunk插件的作用,这里可以返回函数
return dispatch =>{
//异步结束后,手动执行dispatch
setTimeout(() => {
dispatch(addGUN())
}, 2000)
}
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { createStore ,applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import {counter,addGUN,removeGUN,addGunAsync} from './index.redux';
//1.新建store
const store = createStore(counter,applyMiddleware(thunk));
function render() {
//reactDOM 渲染页面
//2.这个store 以在组件属性props传给Component 组件
ReactDOM.render(<App store={store} addGunAsync={addGunAsync} addGUN={addGUN} removeGUN={removeGUN} />, document.getElementById('root'));
registerServiceWorker();
}
render();
//3.以subscribe订阅render的函数 这样我们可以知道state的变化
store.subscribe(render);
app.js
import React from 'react';
class App extends React.Component {
render() {
//4.通过组件的属性props 获取store以及数据操作addGUN
//5.在通过dispatch(addGUN()) 发送action
const store=this.props.store;
const num =store.getState();
const addGUN=this.props.addGUN;
const removeGUN=this.props.removeGUN;
const addGunAsync=this.props.addGunAsync;
return (
<div>
<h1>现在有机枪{num}把</h1>
<button onClick={()=>store.dispatch(addGUN())}>申请武器</button>
<button onClick={()=>store.dispatch(removeGUN())}>上交武器</button>
<button onClick={()=>store.dispatch(addGunAsync())}>拖2天上交武器</button>
</div>
);
}
}
export default App;
点击拖2天上交武器按钮 过2秒后 会自动加1把机关枪 ,这就是异步操作。