上个博客写了何时重构,在公司项目新增功能的时候,遇到了一个接口api,完美符合以上几点。
export function getDirections(data) {
let coordinates = '';
let coordsArray = [];
let paramObject = null;
let dataParams = null; // ?geometries=geojson&access_token=&alternatives=true&steps=true"
let startPoint = '',
directionsInfo = store.state.directions;
if (directionsInfo.routeStartPoint.geometry) {
startPoint = directionsInfo.routeStartPoint.geometry.coordinates
}
coordsArray.push(startPoint);
let pastsPointsInfo = []; //途经点
if (store.state.waypoint.waypointsPast.length > 0) {
for (let waypoint of store.state.waypoint.waypointsPast) {
if(waypoint == undefined) continue;
if (!data.first) {
pastsPointsInfo.push({
id: waypoint.id,
text: waypoint.text,
coordinates: waypoint.geometry.coordinates
});
}
coordsArray.push(waypoint.geometry.coordinates)
}
}
let endPoint = ''; //终点
if (directionsInfo.routeEndPoint.geometry) {
endPoint = directionsInfo.routeEndPoint.geometry.coordinates;
}
coordsArray.push(endPoint);
coordinates = exChangeCode(coordsArray, 'encode');
paramObject = {
// geometries: 'geojson',
access_token: '',
alternatives: true,
steps: true,
location: coordinates,
coordtype: 'sg_polyline'
}
if (!data.first) {
router.push({
query: {
fromname: JSON.stringify({
id: directionsInfo.routeStartPoint.id,
text: directionsInfo.routeStartPoint.text,
coordinates: exChangeCode(directionsInfo.routeStartPoint.geometry.coordinates, 'encode')
}),
waypointsPast: JSON.stringify(pastsPointsInfo),
toname: JSON.stringify({
id: directionsInfo.routeEndPoint.id,
text: directionsInfo.routeEndPoint.text,
coordinates: exChangeCode(directionsInfo.routeEndPoint.geometry.coordinates, 'encode')
}),
queryType: 'direction',
exclude: data.exclude
}
});
}
// //路线偏好设置,(系统推荐、最短路程,不给exclude参数),高速优先(exclude:toll),不做高速(exclude:motorway)
if (data && data.exclude) {
Object.assign(paramObject, {
exclude: data.exclude
}) //
}
dataParams = getParamString(paramObject); //将对象转换成字符串格式
return new Promise((resolve, reject) => {
fetch({
url: `脱敏/driving/${coordinates}${dataParams}`,
method: 'get'
}).then(response => {
let resData = response;
resData.queryParameters = store.state.waypoint.waypointsPast;
resolve(resData);
}).catch(error => {
reject(error);
});
});
}
密密麻麻一长串的函数,真正要阅读起来,还真实有点费劲。
这是一个驾车路径规划的接口,新增了公交和步行路径规划。
因为触发查询的条件几乎一致,最小化的改动代码,从vuex里面的驾车路径规划action入手。
原功能,仅有路径导航。
directions({
commit
}, queryParams) {
// 这里不重点展开,只针对上述文件进行重构
},
在路径规划action添加多个入口,保证旧功能不变的前提,新增功能
directions({ commit }, queryParams) {
const routeType = store.state.type;
if (!routeType || routeType === "drive") {
directionsDriver({ commit }, queryParams);
} else if (routeType === "bus") {
directionsBus({ commit }, queryParams);
} else if (routeType === "walk") {
directionsWalk({ commit }, queryParams);
}
},
因为添加了相似的功能,所以大概率会有很多需要复用的代码。
但是大多数清空和赶工的时候,直接重新拷贝一份代码再做修改,导致出现了太多重复代码。
1 getCoordinates
2 setUrlParams
function getCoordinates(directionsInfo, needPassPoint, waypointsPast) {
// 重构方法:提炼函数(106) 将过长函数中,相同操作的函数提取到一个小函数内
let coordsArray = [];
let startPoint = "";
if (directionsInfo.routeStartPoint.geometry) {
startPoint = directionsInfo.routeStartPoint.geometry.coordinates;
}
coordsArray.push(startPoint);
if (needPassPoint) {
if (waypointsPast.length > 0) {
for (let waypoint of waypointsPast) {
// 重构方法:拆分循环(227)
// 将循环中无法拆分到两部分内容,拆分成2个独立到任务setUrlParams方法中重新循环处理
if (waypoint == undefined) continue;
coordsArray.push(waypoint.geometry.coordinates);
}
}
}
let endPoint = ""; //终点
if (directionsInfo.routeEndPoint.geometry) {
endPoint = directionsInfo.routeEndPoint.geometry.coordinates;
}
coordsArray.push(endPoint);
return exChangeCode(coordsArray, "encode");
}
function setUrlParams(obj) {
// 重构方法:保持对象完整(319)引入state,data,避免过长变量列表
// 重构方法:引入参数对象(140)使用一个对象参数,函数解析获取参数列表,便于扩展
const { type, state, data } = obj;
const { exclude, first } = data || {};
const directionsInfo = state.directions;
const waypointsPast = state.waypoint.waypointsPast;
const pastsPointsInfo = []; // ?作用是什么 途经点
if (waypointsPast.length > 0) {
for (let waypoint of waypointsPast) {
// 重构方法:拆分循环(227)
// 将循环中无法拆分到两部分内容,拆分成2个独立到任务setUrlParams方法中重新循环处理
if (waypoint == undefined) continue;
if (!first) {
pastsPointsInfo.push({
id: waypoint.id,
text: waypoint.text,
coordinates: waypoint.geometry.coordinates
});
}
}
}
router.push({
query: {
fromname: ....,
waypointsPast: ...,
toname: ...
});
}
使用到的重构方法
因为每个接口请求的入参都不一样,所以在各自函数内添加内联函数处理。减少主代码体的行数,增加可读性。
export function getDirections(data) {
...
...
...
// 获取接口请求参数
// 提炼函数
function _getParamsString({ coordinates, data }) {
let paramObject = null;
// let dataParams = null; // ?geometries=geojson&access_token=&alternatives=true&steps=true"
paramObject = {
// geometries: 'geojson',
access_token: "",
alternatives: true,
steps: true,
location: coordinates,
coordtype: "sg_polyline"
};
//路线偏好设置,(系统推荐、最短路程,不给exclude参数),高速优先(exclude:toll),不做高速(exclude:motorway)
if (data && data.exclude) {
Object.assign(paramObject, {
exclude: data.exclude
});
}
return getParamString(paramObject); //将对象转换成字符串格式
}
}
export function getDirections(data) {
const coordinates = getCoordinates(
store.state.directions,
true,
store.state.waypoint.waypointsPast
);
if (!data.first) {
// 设置url参数,记录当前操作状态,页面刷新还原
setUrlParams({
type: "drive",
state: store.state,
data
});
}
return new Promise((resolve, reject) => {
fetch({
url: `脱敏/driving/${coordinates}${_getParamsString({
coordinates,
data
})}`,
method: "get"
})
.then(response => {
resolve(response);
})
.catch(error => {
reject(error);
});
});
// 获取接口请求参数
// 提炼函数
function _getParamsString({ coordinates, data }) {
...
}
}
export function getDirectionsBus(data) {
const { startAddress, endAddress } = data && data.queryPara ? data.queryPara : {};
setUrlParams({
type: "bus",
state: store.state,
data
});
return new Promise((resolve, reject) => {
fetch({
url: `脱敏/integrated${_getParamsString({
startAddress,
endAddress
})}`,
method: "get"
})
.then(response => {
resolve(response);
})
.catch(error => {
reject(error);
});
});
// 获取接口请求参数
// 提炼函数
function _getParamsString({ startAddress, endAddress }) {
...
}
}
代码肯定还有很多可以优化和重构的地方,今天先把书上看到用得上的方法在实际代码里面实践一下。实践不仅理清了原代码的逻辑,还简洁了函数的结构。