[英]Javascript - I have 300 if/else statements. Should I be using switch instead?
我有一个查找路径并重写路径的 js 文件,它有 300 多个 if/else 语句。 我正在寻找清理它的方法,但我还需要确保它对于下一个将要处理它的人来说是可读的。 我的第一个想法是将所有这些 if 语句转换为三元或 switch 语句,但我不确定这是否是最好的方法。 我试图平衡编写“更好”代码的冲动,但我还需要确保它保持可读性,并且当前的 if/else 结构读起来很好。
例子:
if (request.uri.match(^\/path1\/.*$)) {
request.uri = request.uri.replace(/^\/path1\/(.*)$/) "newPath" + "$1");
} else if (request.uri.match(^\/path2\/.*$)) {
request.uri = request.uri.replace(/^\/path2\/(.*)$/) "newPath" + "$1");
} else if (request.uri.match(^\/path3\/.*$)) {
request.uri = request.uri.replace(/^\/path3\/(.*)$/) "newPath" + "$1");
}
我会说 300 个 if 语句中的 75% 看起来相似。 path1、path2 示例过于简单,每个示例的正则表达式从简单到复杂。 除了重写 URL 之外,另外 25% 还包含其他逻辑。 考虑注入标头,或者在某些情况下多一层嵌套的 if/else 语句。
以下是其中一些可能看起来的示例:
else if (request.uri.match(^\/path3(-new)?\/.*$)) {
request.headers['header'] = {"value": "something"};
if (request.uri.match(^\/path3\/.*$)) {
request.uri = request.uri.replace(/^\/path3\/(.*)$/) "/newPathA/" + "$1");
} else if (request.uri.match(^\/path3-new\/.*$)) {
request.uri = request.uri.replace(/^\/path3-new\/(.*)$/) "/newPathB/" + "$1");
}
}
我走上了构建函数来处理不同事情的道路,比如 uri 替换行。 挑战在于函数要替换的代码并不难,而且感觉有点浪费。 我可以有一条线来做到这一点:
request.uri = request.uri.replace(/^\/path3-new\/(.*)$/) "/newPathB/" + "$1");
或者我可以有这个:
function pathModifier(newPath) {
request.uri = reqUri.replace(/^(\/.*?[\/])(.*)$/, newPath);
return;
}
pathRewriter("/newPathA/" + "$1");
我没有存很多钱,这让我把它传递给的人更难阅读。
那么,你会怎么做?
如果你有很多情况,我建议在查找键和它们的值之间使用 HashMap/Object 到 map。
const paths = {
'/old/path/to/a': '/new/path/to/a',
'/old/path/to/b': '/new/path/to/b',
'/old/path/to/c': '/new/path/to/c'
}
function getNewPath(oldPath) {
return paths[oldPath] || '/fallback/not/found'
}
或者,如果您必须处理不同的业务逻辑,您也可以返回 function
const paths = {
'/old/path/to/a': () => { return modifyA() },
'/old/path/to/b': () => { return modifyB() },
'/old/path/to/c': () => { return modifyC() },
}
function getNewPath(oldPath) {
return paths[oldPath]()
}
对于大多数情况,我会使用声明性方法,并且仍然公开一种通过传递自定义 function 来扩展它的方法。
这样,您的代码中的重复次数就会减少,同时仍然提供所需的灵活性。
像这样的东西:
const rewrites = {
'/path1/': ['/newPathA/'],
'/path2/': ['/newPathB/'],
'/path3/': ['/newPathC1/', { headers: { name: 'value' } }],
'/path3-new/': ['/newPathC2/', { headers: { name: 'value' } }],
'/path4': ['/newPathD', { headers: { name: 'value' }, callback: req => {
req.customProperty = 123
req.doCustomStuff()
} }]
}
function handleRewrites (req, rewrites) {
const [newPath, options] = Object.keys(rewrites)
.find(oldPath => req.uri.startsWith(oldPath)) ?? []
if (newPath) {
req.uri = newPath + req.uri.slice(oldPath.length)
if (options?.headers) Object.assign(req.headers, options.headers)
options?.callback?.(req)
}
}
当然,您可以自由设计如何声明重写的“领域特定语言”,因为它最适合您的用例。 我选择了一个 object,其中旧路径作为键, [newPath, optionalOptionsObject]
作为值,因为大多数时候我希望只有一个oldPath
=> newPath
转换,但它当然可能会有所不同。
如果您在某些情况下需要例如实际的正则表达式,您当然可以更改它并执行类似数组的操作,然后在其中使用[oldPathOrRegex, newPath, optionalOptionsObject]
格式的值。 然后,您可以允许简单的字符串路径,但也允许正则表达式(取决于它是instanceof RegExp
,您将应用一种逻辑或另一种逻辑,允许您在声明重写时轻松指定两种类型的路径选择器)。
当然,您仍然需要多次指定多个路由的公共标头。 允许使用与任何每个路由属性合并的公共属性指定(甚至可能是嵌套的)重写组的一种可能方法是创建一个 function,它采用公共设置和另一个重写列表并返回每个的扩展版本给定重写,然后用...
传播 function 的结果:
function withOptions (commonOptions, rewrites) {
for (const rewrite of Object.values(rewrites)) {
if (!rewrite[1]) rewrite[1] = {}
const rewriteOptions = rewrite[1]
if (commonOptions.headers || rewriteOptions.headers) {
rewriteOptions.headers = {
...commonOptions.headers,
...rewriteOptions.headers
}
}
if (commonOptions.callback || rewriteOptions.callback) {
const childCallback = rewriteOptions.callback
rewriteOptions.callback = req => {
commonOptions.callback?.(req)
childCallback?.(req)
}
}
}
return rewrites
}
const rewrites = {
'/path1/': ['/newPathA/'],
'/path2/': ['/newPathB/'],
...withOptions({ headers: { name: 'value' } }, {
'/path3': ['/newPathC2/'],
'/path3-new': ['/newPathC3/']
}),
'/path4': ['/newPathD', { headers: { name: 'value' }, callback: req => {
req.customProperty = 123
req.doCustomStuff()
} }]
}
请注意,在此示例中,我编写了withOptions
,因此它会改变给定的重写,因为这是最简单的方法,并且我认为无论如何它都会传递 object 文字。 如果这不是真的,当然可以将其更改为返回副本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.