# 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)
← 浏览器渲染原理 WebWorker 的使用 →