You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中如何重构嵌套if-else处理日志等横切关注点避免上帝方法?

优化方案

第一步:合并零散参数为配置对象

原来的多布尔参数扩展成本极高,先合并为单个配置对象,同时配置默认值,调用时不需要传全量参数:

const DEFAULT_LOG_OPTIONS = {
  enableStartLog: false,
  enableSuccessLog: false,
  enableFailureLog: false,
  onlyLogExternal: false,
}

fetch 方法入参调整为(url, options = {}),执行时先合并配置:const logOptions = {...DEFAULT_LOG_OPTIONS, ...options}

第二步:抽离统一的日志准入判断逻辑

把散落在各个流程的日志判断逻辑抽为独立函数,消除多层嵌套if:

function shouldLog(url, options, logType) {
  // 先校验对应类型日志是否开启
  if(!options[`enable${logType}Log`]) return false
  // 校验是否仅允许外部链接日志
  if(options.onlyLogExternal && !isExternalLink(url)) return false
  return true
}

原来的多层嵌套判断直接简化为一行:
if(shouldLog(url, logOptions, 'Start')) Logger.logFetchStartedEvent()

第三步:用映射表替代错误类型分支判断

错误类型的多if/else分支完全可以用对象映射替代,后续新增错误类型不需要修改核心逻辑:

const ERROR_LOG_MAP = {
  [TimeOut]: Logger.logFetchFailedTimeOutEvent,
  [404]: Logger.logFetchFailed404Event,
  default: Logger.logFetchFailedEvent
}

catch块的错误日志逻辑简化为:

if(shouldLog(url, logOptions, 'Failure')) {
  const logFn = ERROR_LOG_MAP[errorType(error)] || ERROR_LOG_MAP.default
  logFn()
}

第四步:预置常用场景封装,降低调用成本

针对通用场景提前封装专用方法,调用方不需要感知配置细节:

// 全量日志场景
function fetchWithFullLog(url, options = {}) {
  return fetchApiData(url, {
    enableStartLog: true,
    enableSuccessLog: true,
    enableFailureLog: true,
    ...options
  })
}
// 仅打印错误日志场景
function fetchWithErrorLogOnly(url, options = {}) {
  return fetchApiData(url, {
    enableFailureLog: true,
    ...options
  })
}
// 仅外部链接打印日志场景
function fetchLogExternalOnly(url, options = {}) {
  return fetchApiData(url, {
    enableStartLog: true,
    enableSuccessLog: true,
    enableFailureLog: true,
    onlyLogExternal: true,
    ...options
  })
}

重构后完整代码

const DEFAULT_LOG_OPTIONS = {
  enableStartLog: false,
  enableSuccessLog: false,
  enableFailureLog: false,
  onlyLogExternal: false,
}

const ERROR_LOG_MAP = {
  [TimeOut]: Logger.logFetchFailedTimeOutEvent,
  [404]: Logger.logFetchFailed404Event,
  default: Logger.logFetchFailedEvent
}

function shouldLog(url, options, logType) {
  if(!options[`enable${logType}Log`]) return false
  if(options.onlyLogExternal && !isExternalLink(url)) return false
  return true
}

function fetchApiData(url, options = {}) {
  const logOptions = {...DEFAULT_LOG_OPTIONS, ...options}

  if(shouldLog(url, logOptions, 'Start')) {
    Logger.logFetchStartedEvent()
  }

  try {
    const data = backendApi.get(url)
    if(shouldLog(url, logOptions, 'Success')) {
      Logger.logFetchSucceededEvent()
    }
    return data
  } catch (error) {
    if(shouldLog(url, logOptions, 'Failure')) {
      const errType = errorType(error)
      const logFn = ERROR_LOG_MAP[errType] || ERROR_LOG_MAP.default
      logFn()
    }
  }
}

// 预置场景导出
export { fetchWithFullLog, fetchWithErrorLogOnly, fetchLogExternalOnly }

扩展优势

  • 无任何嵌套if/else,所有逻辑平层展开,可读性极强
  • 新增日志规则只要修改shouldLog函数,不需要调整fetch核心流程
  • 新增错误类型只要往ERROR_LOG_MAP加对应映射即可,符合开闭原则
  • 新增场景只要加一行预置封装,不需要修改核心逻辑
  • 所有配置带默认值,调用方不需要感知无关参数

内容的提问来源于stack exchange,提问作者nexlin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:48:04