最近在读Redux相关源码,现将自己实现的代码和理解贴上,后期再补充详细~
使用redux-promise中间件,允许action是一个promise,在promise中,如果要触发action,则通过调用resolve来触发。
实现原理:如果action是一个promise,则会等待promise完成,将完成的结果作为action触发,如果action不是一个promise,则判断其payload是否是一个promise,如果是,等待promise完成,然后将得到的结果作为payload的值触发。
实现redux-promise:先判断action是不是一个标准的flux action(这里使用了一个第三方库is-promise,判断参数是否是promsie)
import { isPlainObject, isString } from "lodash"
import isPromise from "is-promise"export default ({ dispatch }) => next => action => {if (!isFSA(action)) {//如果不是一个标准的action//如果action是一个promise,则将其resolve的值dispatch,否则,不做任何处理,交给下一个中间件return isPromise(action) ? action.then(dispatch) : next(action);}return isPromise(action.payload) ?action.payload.then(payload => dispatch({ ...action, payload })).catch(error => dispatch({ ...action, payload: error, error: true })) :next(action)
}/*** 判断一个action是不是标准的flux的action* @param {*} action */
function isFSA(action) {//action必须是一个平面对象 plain-object//action.type必须是一个字符串//action的属性不能包含其他非标准属性 标准属性["type", "payload", "error", "meta"]return isPlainObject(action)&&isString(action.type)&&Object.keys(action).every(key => ["type", "payload", "error", "meta"].includes(key));
}
redux-promise的几种使用方法,以下都是在action生成器中的使用场景:
// 直接返回一个promise
export function fetchStudents() {return new Promise(resolve => {setTimeout(() => {const action = setStudentAndTotal([{ id: 1, name: 'zc' }, { id: 2, name: 'gg' }],100)resolve(action);},1000)})
}
// 结合async await使用
export async function fetchStudents(condition) {const resp = await searchStudents(condition)return setStudentAndTotal(resp.datas, resp.cont);
}
// payload接收一个promise
export async function fetchStudents(condition) {return {type: actionTypes.setStudentAndTotal, payload: await searchStudents(condition).then(resp => ({datas: resp.datas,total: resp.cont}))}
}