前些天自己实现了一个简单的redux 下面来看代码
自定义reducer
123456789101112131415161718192021function reducer1(state = {qq:3}, action) {switch (action.type) {case 'changeQQ':return {...state, qq: action.qq}default:return state}}function reducer2(state = {ww:3}, action) {switch (action.type) {case 'changeWW':return {...state, ww: action.ww}default:return state}}实现combineReducer,把多个reducer合并在一起
123456789101112131415const combineReducers = (reducerObj) => {const returnObj = {};for(const [key, value] of Object.entries(reducerObj)) {// 获得初始的值returnObj[key] = value(undefined, {type:''});}returnObj.receiveAction = (action) => {for (let i in reducerObj) {let state = returnObj[i];state = reducerObj[i](state, action);returnObj[i] = state;}}return returnObj;}
可以看到combineReducer其实就是把reducer合并在一起
下面就是createStore的实现了
1234567891011121314151617181920212223242526272829303132const createStore = (reducers, middleware) => {let listeners = [];let store = {getState(){const state = {};for(let i in reducers) {if (typeof reducers[i] == 'object') {state[i] = reducers[i]}}return state;},dispatch(action){const prevState = store.getState();reducers.receiveAction(action);const nowState = store.getState();if (listeners.length) {for(let fn of listeners)fn(prevState, nowState);}},subscribe(fn){listeners.push(fn);return () => {listeners = []}}}// 注意这里的dispatch是经过中间件修饰后的dispatchreturn {...store, dispatch: middleware(store)}}getState比较好理解, 就是获取每个reducer的状态
- dispatch和subscribe也是store上面本来就有的属性
这里加入了中间件
applyMiddleware的实现
12345678910111213141516171819202122232425262728293031const applyMiddle = (...middlewares) => {return store => {let dispatch = store.dispatch;let middlewareAPI = {getState: store.getState,dispatch: (action) => dispatch(action)}chain = middlewares.map(middleware => middleware(middlewareAPI));dispatch = compose(...chain)(store.dispatch);return dispatch;}}const logger1 = ({ getState, dispatch }) => next => action => {console.log('【logger111】即将执行:', action)let returnValue = next(action);console.log('【logger222】执行完成后 state:', getState())return returnValue}const logger2 = ({ getState, dispatch }) => next => action => {console.log('【logger333】即将执行:', action)console.log(getState(), 'dddddddd');let returnValue = next(action);console.log('【logger333】执行完成后 state:', getState())// return returnValue}
上面可能有点难理解, 我们看看compose是干嘛的
- compose函数1234567891011function compose(...funcs) {if (funcs.length === 0) {return arg => arg}if (funcs.length === 1) {return funcs[0]}return funcs.reduce((a, b) => (...args) => a(b(...args)))}
实际compose就是把fn1(fn2(fn3(x))) => compose(f1,f2,f3)x
实验成果
1234567891011121314151617181920const reducers = combineReducers({reducer1, reducer2});const store = createStore(reducers, applyMiddle(logger, logger1, logger2));const unsubscribe = store.subscribe((a, b) => {console.log('prev is', a);console.log('now is', b);})console.log(store.getState());store.dispatch({type: 'changeQQ', qq: 10});console.log(store.getState());unsubscribe();store.dispatch({type: 'changeWW', ww: 110});console.log(store.getState());最后来一个异步任务收尾
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172class Concurrently<T = any> {private tasksQueue: (() => Promise<T>)[] = [];private tasksActiveCount: number = 0;private tasksLimit: number;public constructor(tasksLimit: number) {if (tasksLimit < 0) {throw new Error('Limit cant be lower than 0.');}this.tasksLimit = tasksLimit;}private registerTask(handler) {this.tasksQueue = [...this.tasksQueue, handler];this.executeTasks();}private executeTasks() {while (this.tasksQueue.length && this.tasksActiveCount < this.tasksLimit) {const task = this.tasksQueue[0];this.tasksQueue = this.tasksQueue.slice(1);this.tasksActiveCount += 1;task().then((result) => {this.tasksActiveCount -= 1;this.executeTasks();return result;}).catch((err) => {this.tasksActiveCount -= 1;this.executeTasks();throw err;});}}public task(handler: () => Promise<T>): Promise<T> {return new Promise((resolve, reject) =>this.registerTask(() =>handler().then(resolve).catch(reject),),);}}export default Concurrently;const waitFor = (time: number) =>new Promise((resolve) => {return setTimeout(resolve, time);});const lightTask = () => waitFor(5000);const heavyTask = () => waitFor(100000);[heavyTask, heavyTask].concat([...new Array(1000)].map(() => lightTask)).map((task, i) =>// 注意这里task进去的是一个async函数concur.task(async () => {console.log('executing', i);await task();console.log('done', i);}),);
上述用js实现concurrent任务, 并限制concurrent的limit