redux基础知识 | redux(二)javascript
在上一篇文章中,咱们经实现了一个基本的redux,那若是咱们想在redux中实现异步的操做怎么办?java
好比下面的操做react
pages/ReduxPage.jsgit
import React, { Component } from 'react'
import store from '../store/'
export default class ReduxPage extends Component {
componentDidMount() {
this.unsubscribe = store.subscribe(() => {
this.forceUpdate()
})
}
componentWillUnmount() {
if(this.unsubscribe) {
this.unsubscribe()
}
}
asyAdd = () => {
store.dispatch((dispatch,getState) => {
setTimeout(() => {
dispatch({type: 'ADD', payload: 1})
}, 1000)
})
}
promiseAdd = () => {
store.dispatch(Promise.resolve({type: "MINUS", payload: 1}));
}
render() {
return(
<div> <h3>Reduxpage</h3> <p>{count}</p> <button onClick={this.asyAdd}>异步+</button> <button onClick={this.promiseAdd}>promise-</button> </div>
)
}
}
复制代码
上面的操做咱们有两个异步的操做,分别是是setTimeout和Promise。因为咱们的action触发了之后,就会立马去reducer里面执行state的更新,因此咱们想要实现异步的操做,就必须在dispatch的时候,去作一些操做。github
在store里面,有个方法叫作applyMiddleware(),它能够接收一些参数,二接受的这些参数,就是咱们处理异步的中间件,咱们看一下怎么使用的。redux
import { createStore, applyMiddleware } from 'redux';
import logger from 'react-logger';
import thunk from 'react-thunk';
import rdPromise from 'react-promise'
const countReducer = (state = 0, action) => {
const {type, payload} = action
switch(type) {
case 'ADD':
return state + payload;
case 'MINUS':
return state - payload;
default:
return state
}
}
const store = createStore(
countReducer,
applyMiddleware(thunk, logger, rdPromise)
)
export default store;
复制代码
applyMiddleware()接收了三个参数:promise
这样子,咱们上面的异步操做按钮就能够正常的工做了,下面让咱们看看源码如何实现的。bash
Jreact/createStore.jsapp
export default function createStore(reducer, enhancer) {
if(enhancer) {
return enhancer(createStore)(reducer)
}
}
复制代码
在createStore里面,咱们须要判断一下createStore的第二个参数,也就是applyMiddleware,有的话,就把createStore和reducer传给它,咱们须要在内部去使用这两个参数。异步
Jreact/applyMiddleware.js
export default function applyMiddleware(...middlewares) {
return createStore => reducer => {
const store = createStore(reducer)
let dispatch = store.dispatch
const midApi = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
const middlewareChain = middlewares.map(md => md(midApi))
dispatch = compose(...middlewareChain)(store.dispatch);
return {
...store,
dispatch
}
}
}
// 聚合函数
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg;
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce((a, b) => (...args) => {
return a(b(...args));
});
}
复制代码
applyMiddleware(...middlewares)就是接收的thunk, logger, rdPromise这几个参数,而后在里面对dispatch作了增强。咱们对middlewares作了便利,也就是thunk, logger, rdPromise,他们会接收getState和dispatch,而后在每一个中间件的内部独立处理本身的逻辑,处理完成之后会造成一个middlewareChain,使用一个聚合函数compose,把middlewareChain里面的函数聚合一个,增强了dispatch,最后返回出去,这样就能够在dispatch的时候,作一些操做了。
下面是三个中间件的实现
Jreact/thunk.js
export default function thunk({dispatch, getState}) {
return next => action => {
if(typeof action === 'function') {
return action(dispatch, getState)
}
return next(action)
}
}
复制代码
Jreact/logger.js
export default function logger({getState}) {
return next => action => {
console.log('prevState', getState());
const newState = next(action)
console.log('nextState', getState());
return newState
}
}
复制代码
Jreact/rdPromise.js
import { isFSA } from 'flux-standard-action';
import isPromise from 'is-promise';
export default function rdPromise({dispatch}) {
return next => action => {
if(!isFSA(action)) {
return isPromise(action) ? action.then(dispatch) : next(action)
}
return next(action)
}
}
复制代码
这是三个函数,经过聚合函数依次执行他们,就能够了。
至此,redux的源码就讲的差很少了