# js一些中间件设计

# axios

const axios = (config) => {
	if (config.error) {
		return Promise.reject({ error: 'axios is error' })
	} else {
		return Promise.resolve({
			...config,
			result: 'SUCCESS'
		})
	}
}

// 构造一个对象 存放拦截器
axios.interceptors = {
	request: [],
	response: []
}

// 注册请求拦截器
axios.useRequestInterceptor = (resolved, rejected) => {
	axios.interceptors.request.push({ resolved, rejected })
}

// 注册响应拦截器
axios.useResponseInterceptor = (resolved, rejected) => {
	axios.interceptors.response.push({ resolved, rejected })
}

// 运行拦截器
axios.run = (config) => {
	const chain = [
		{
			resolved: axios,
			rejected: undefined
		}
	]

	// // 把请求拦截器往数组头部推
	axios.interceptors.request.forEach((interceptor) => {
		chain.unshift(interceptor)
	})
	//  // 把响应拦截器往数组尾部推
	axios.interceptors.response.forEach((interceptor) => {
		chain.push(interceptor)
	})

	let promise = Promise.resolve(config)
	while (chain.length > 0) {
		const { resolved, rejected } = chain.shift()
		promise = promise.then(resolved, rejected)
	}
	return promise
}

axios.useRequestInterceptor(
	(config) => {
		config = {
			RequestInterceptor: 'RequestInterceptor1',
			...config
		}
		return config
	},
	(err) => {}
)

axios.useRequestInterceptor(
	(config) => {
		config = {
			RequestInterceptor2: 'RequestInterceptor2',
			...config,
			error: true
		}
		return config
	},
	(err) => {}
)

axios.useResponseInterceptor(
	(config) => {
		return { ...config, response: 'response' }
	},
	(error) => {
		console.log(error, 'sss')
	}
)

axios
	.run({
		method: 'POST'
	})
	.then((res) => {
		console.log(res)
	})

# Redux 中间件

主要借助compose函数

function compose(...funcs) {
  // [abc, pow2, add]
  return funcs.reduce((a, b) => {
    return function (...args) {
      return a(b(...args));
    };
  });
}

/* function compose2(funcs) {
  return function (...args) {
    const funcArr = Array.prototype.slice.call(funcs);
    let result = funcArr.pop()(...args);
    for (let i = funcArr.length - 1; i >= 0; i--) {
      result = funcArr[i](result);
    }
    return result;
  };
}
 */
function compose2(...middles) {
  return function newDispatch(dispatch) {
    let _dispatch = middles.pop()(dispatch);
    for (let i = middles.length - 1; i >= 0; i--) {
      _dispatch = middles[i](_dispatch);
    }
    return _dispatch;
  };
}

function createStore(reducer, middlewares) {
  let currentState;

  function dispatch(action) {
    currentState = reducer(currentState, action);
  }

  function getState() {
    return currentState;
  }

  dispatch({ type: 'INIT' });

  let enhancedDispatch = dispatch;
  if (middlewares) {
    enhancedDispatch = compose2(...middlewares)(dispatch);
  }
  return {
    dispatch: enhancedDispatch,
    getState
  };
}

const otherDummyMiddleware = (dispatch) => {
  // 返回一个新的dispatch
  return (action) => {
    console.log(`type in dummy is ${action.type}`);
    return dispatch(action);
  };
};

// 这个dispatch其实是otherDummyMiddleware执行后返回otherDummyDispatch
const typeLogMiddleware = (dispatch) => {
  // 返回一个新的dispatch
  return ({ type, ...args }) => {
    console.log(`type is ${type}`);
    return dispatch({ type, ...args });
  };
};

function counterReducer(state, action) {
  const { type, payload } = action;
  switch (type) {
    case 'INIT':
      debugger;
      return {
        count: 0
      };
    case 'add':
      debugger;
      return { ...state, count: state.count + payload };

    default:
      return state;
  }
}

const counterStore = createStore(counterReducer, [
  typeLogMiddleware,
  otherDummyMiddleware
]);
counterStore.dispatch({
  type: 'add',
  payload: 11
});

console.log(counterStore.getState());
	

# Vuex 中间件

class Vuex {
	constructor({ state, action }) {
		this.state = state
		this.action = action
		this._actionSubscribers = []
	}

	dispatch(action) {
		this._actionSubscribers.forEach((sub) => {
			const beforeFunc = sub.before
			if (beforeFunc && typeof beforeFunc === 'function') {
				beforeFunc(action, this.state)
			}
		})
		const { type, payload } = action
		this.action[type](this.state, payload).then(() => {
			this._actionSubscribers.forEach((sub) => {
				const afterFunc = sub.after
				if (afterFunc && typeof afterFunc === 'function') {
					afterFunc(action, this.state)
				}
			})
		})
	}

	subscribeAction(action) {
		this._actionSubscribers.push(action)
		return function unsubscribeAction() {
			for (let i = 0, len = this._actionSubscribers.length; i < len; i++) {
				if (this._actionSubscribers[i] === action) {
					this._actionSubscribers.splice(i, 1)
					break
				}
			}
		}
	}
}

const store = new Vuex({
	state: {
		count: 0
	},
	action: {
		async add(state, payload) {
			state.count += payload
		}
	}
})

store.subscribeAction({
	before: function (action, state) {
		console.log('before')
	},
	after: function (action, state) {
		console.log('after')
	}
})

store.dispatch({
	type: 'add',
	payload: 10
})

console.log(store.state.count)	
上次更新: 1/22/2025, 9:39:13 AM