反向代理
与一般访问流程相比,使用反向代理后,直接收到请求的服务器是代理服务器,然后将请求转发给内部网络上真正进行处理的服务器,得到的结果返回给客户端。反向代理隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见。而与此对应的正向代理,使真实客户端对服务器不可见。
拦截器
拦截器是动态代理的方便写法,将想要插入的逻辑利用我们定义的拦截器接口抛给外部实现。动态代理,可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作
我们在项目中经常使用 Axios 的实例来进行 HTTP 的请求,使用拦截器 interceptor 可以提前对 request 请求和 response 返回进行一些预处理,还有 vue-router、react-router 路由跳转的拦截器,可以进行一些路由跳转的预处理等操作
interface ConfigType {
message: string
}
type Fun = (value: ConfigType) => ConfigType
interface InterceptorObj {
resolved: Fun;
rejected?: Fun
}
type InterceptorFun = (resolved: Fun, rejected?: Fun) => void
interface AxiosType {
interceptors: {
request: Array<InterceptorObj>;
response: Array<InterceptorObj>;
};
useRequestInterceptor: InterceptorFun;
useResponseInterceptor: InterceptorFun;
run: (config: ConfigType) => Promise<ConfigType>;
}
class Axios implements AxiosType {
interceptors: {
request: Array<InterceptorObj>;
response: Array<InterceptorObj>;
};
constructor() {
this.interceptors = {
request: [],
response: [],
};
}
// 注册请求拦截器
useRequestInterceptor(resolved: Fun, rejected?: Fun) {
this.interceptors?.request.push({ resolved, rejected });
}
// 注册响应拦截器
useResponseInterceptor(resolved: Fun, rejected?: Fun) {
this.interceptors?.response.push({ resolved, rejected });
}
run(config: ConfigType) {
const chain: Array<InterceptorObj> = [];
// 把请求拦截器往数组头部推
this.interceptors?.request.forEach((interceptor: InterceptorObj) => {
chain.unshift(interceptor);
});
// 把响应拦截器往数组尾部推
this.interceptors?.response.forEach((interceptor: InterceptorObj) => {
chain.push(interceptor);
});
let promise = Promise.resolve(config);
// 利用promise.then的能力递归执行所有的拦截器
while (chain.length > 0) {
const current = chain.shift()
// const { resolved, rejected } = current;
promise = promise.then(current?.resolved, current?.rejected);
}
//响应拦截器处理过后的promise
return promise;
}
}
前端框架的数据响应式化
要实现数据的响应式变化,我们需要拦截一个对象的读取和设置操作,在读取(get、has、ownKeys)时收集依赖,在设置时(deleteProperty、set)时触发依赖。
function reactive(obj: any, isShallow = false): boolean {
return new Proxy(obj, {
get(target, key, receiver) {
// 收集依赖
track(target, key);
const result = Reflect.get(target, key, receiver);
if (isShallow) {
return result;
}
if (typeof result === "object" && result !== null) {
return reactive(result);
}
return result;
},
has(target, key) {
// 收集依赖
track(target, key);
return Reflect.has(target, key);
},
ownKeys(target) {
// 收集依赖
track(target, KEY);//KEY由Symbol()生成
return Reflect.ownKeys(target);
},
deleteProperty(target, key) {
const hadKey = Object.prototype.hasOwnProperty.call(target, key);
const result = Reflect.deleteProperty(target, key);
if (hadKey && result) {
// 触发依赖
trigger(target, key, "DELETE");
}
return result;
},
set(target, key, newVal, receiver) {
const type = Object.prototype.hasOwnProperty.call(target, key)
? "SET"
: "ADD";
const oldVal = target[key];
const result = Reflect.set(target, key, newVal, receiver);
if (oldVal !== newVal) {
// 触发依赖
trigger(target, key, type);
}
return result;
},
});
}
缓存代理
备忘模式就是使用缓存代理的思想,将复杂计算的结果缓存起来,下次传参一致时直接返回之前缓存的计算结果。