需求
在开发一个SPA应用时,必然会遇到与后台接口进行ajax的交互。为了项目结构的维护性、可读性,我们总会去做一些相应的处理。如:
- URL集中管理
- 拦截请求
- 拦截响应
在这里,我们主要去实现URL的集中管理方案。
抛出问题
v1: 需求问题
- 如何集中管理URL
- 如何提取出请求地址中相同的内容
- 如何区分接口环境,如['开发环境','上线环境']
v2: 需求问题
- 如何在定义URL时,只写入不同的url即可。相同内容自动拼接,无需前置人为的拼接。
- 如何根据不同的路由类型,去区分请求接口的类型。
技术可行性分析
v1: 需求解决思路
- 可以使用ES6 import export 的方法实现 URl集中管理
- 可以使用“变量拼接、字符串模版解析”的方式,去提取地址中相同的内容
- 可以使用 process.env.NODE_ENV 自定义环境变量,识别此时的运行环境
v2: 需求解决思路
- 可以使用ES6 中的 proxy 实现
代码实现
v1: code
// 联调环境接口判断
const baseUrlEnv = {
development: '/test',
production: '/online'
};
// 请求接口地址
const baseUrl = 'http://www.xxx.com/' + baseUrlEnv[process.env.NODE_ENV];
// 定义URL
const URLSource = {
// 这里定义 account 主要是为了更加的细化请求地址
account: { // 账户类型接口
userInfo: baseUrl + '/v1/getUserInfo',
userlist: `${baseUrl}/v1/getUserList`,
}
};
export default URLSource;
复制代码
v2: code
// 定义URL
const URLSource = {
// 这里定义 account 主要是为了更加的细化请求地址
account: { // 账户类型接口
userInfo: '/v1/{type}/getUserInfo',
userlist: '/v1/{type}/getUserList',
}
};
// 联调环境接口判断
const baseUrl = {
development: '/test',
production: '/online'
};
// 代理监听 URL配置
const handler = {
get(target, key) { // get 的trap 拦截get方法
let value = target[key];
try {
return new Proxy(value, handler); // 使用try catch 巧妙的实现了 深层 属性代理
} catch (err) {
if (typeof value === 'string') {
// 向请求地址动态绑定执行环境 如: test
value = baseUrl[process.env.NODE_ENV] + value;
// 替换当前浏览器的类型 通过获取路由中的第一个路径去区分
if (value.includes('{type}')) {
// 获取 当前浏览器 pathName 路由中的第一个类型
let currentType = window.location.pathname.split('/').filter((item) => {
return item;
});
currentType = currentType.length > 0 ? currentType[0].toLocaleLowerCase() : '';
if (['china', 'Korea'].includes(currentType)) {
value = value.replace('{type}', currentType);
}
}
}
return value;
}
},
set(target, key) { // 阻止外部误操作,导致URL配置文件被修改,设置属性为只读属性
try {
return new Proxy(target[key], handler);
} catch (err) {
return true;
}
}
};
const URL = new Proxy(URLSource, handler);
export default URL;
复制代码