需求
在開發一個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;
複製程式碼