原来的实现
import { SelectProps } from 'antd';
import { useState } from 'react';
import { ShardingComponentEnum } from '~/api-mongodbx/group/index.enum';
import { IChosenServers } from '../index.type';
export const useAliasOption = () => {
const [aliasOptions, setAliasOptions] = useState<SelectProps['options']>([]);
const generateAliasOptions = (
chosenServers?: IChosenServers,
shardComponent?: ShardingComponentEnum,
shardId?: string
) => {
if (chosenServers?.servers) {
const optionsTemp = chosenServers.servers.map((item) => {
return {
label: item.alias,
value: item.alias
};
});
setAliasOptions(optionsTemp);
} else if (chosenServers?.configServer) {
let optionsTemp: SelectProps['options'] = [];
switch (shardComponent) {
case ShardingComponentEnum['config-servers']:
optionsTemp = chosenServers.configServer.map((item) => {
return {
label: item.alias,
value: item.alias
};
});
break;
case ShardingComponentEnum.mongos:
optionsTemp = chosenServers.mongos?.map((item) => {
return {
label: item.alias,
value: item.alias
};
});
break;
case ShardingComponentEnum.shards:
optionsTemp = chosenServers.shards?.[shardId ?? '']?.map((item) => {
return {
label: item.alias,
value: item.alias
};
});
break;
}
setAliasOptions(optionsTemp || []);
}
};
return {
aliasOptions,
setAliasOptions,
generateAliasOptions
};
};
存在的问题
chosenServers对象结构复杂,并且各属性(items)较多,那么每次调用generateAliasOptions时遍历会非常耗费性能
export interface IChosenServers {
servers?: IChosenServerItem[];
configServer?: IChosenServerItem[];
mongos?: IChosenServerItem[];
shards?: {
[key: string]: IChosenServerItem[];
};
}
export interface IChosenServerItem {
alias: string;
ip: string;
port: number;
cell_id: string;
server_id: string;
}
- 分支太多,且同时使用了if 和switch,代码可读性不强
如何优化
将主机映射为option
通过观察源码,可以发现其实从主机到源码的过程基本都是遍历servers,然后将其转换为SelectProps['options],所以可以将其封装成一个函数
const mapServersToOptions = (servers?: IChosenServerItem[]) => {
return (
servers?.map((item) => ({
label: item.alias,
value: item.alias
})) ?? []
);
};
重构switch-case语句
将switch语句提取为独立的函数或使用对象映射的方式来简化代码,增强代码的可读性和易维护性
const { configServer, mongos, shards } = chosenServers as IChosenServers;
const serversMap = {
[ShardingComponentEnum['config-servers']]: () => configServer,
[ShardingComponentEnum.mongos]: () => mongos,
[ShardingComponentEnum.shards]: () => shards?.[shardId ?? '']
};
const serversGetter = serversMap[shardComponent as ShardingComponentEnum];
if (serversGetter) {
const servers = serversGetter();
if (servers) {
options = mapServersToOptions(servers);
}
}
修改后完整源码
import { SelectProps } from 'antd';
import { useState } from 'react';
import { ShardingComponentEnum } from '~/api-mongodbx/group/index.enum';
import { IChosenServerItem, IChosenServers } from '../index.type';
export const useAliasOption = () => {
const [aliasOptions, setAliasOptions] = useState<SelectProps['options']>([]);
const mapServersToOptions = (servers?: IChosenServerItem[]) => {
return (
servers?.map((item) => ({
label: item.alias,
value: item.alias
})) ?? []
);
};
const generateAliasOptions = (
chosenServers?: IChosenServers,
shardComponent?: ShardingComponentEnum,
shardId?: string
) => {
let options;
if (chosenServers?.servers) {
options = mapServersToOptions(chosenServers.servers);
} else if (
chosenServers?.configServer &&
chosenServers.mongos &&
chosenServers.shards
) {
const { configServer, mongos, shards } = chosenServers as IChosenServers;
const serversMap = {
[ShardingComponentEnum['config-servers']]: () => configServer,
[ShardingComponentEnum.mongos]: () => mongos,
[ShardingComponentEnum.shards]: () => shards?.[shardId ?? '']
};
const serversGetter = serversMap[shardComponent as ShardingComponentEnum];
if (serversGetter) {
const servers = serversGetter();
if (servers) {
options = mapServersToOptions(servers);
}
}
}
setAliasOptions(options || []);
};
return {
aliasOptions,
setAliasOptions,
generateAliasOptions
};
};