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

如何对HTTP请求的成功与错误处理函数实现DRY原则?

兄弟,我太懂你这种要写一百多个请求处理函数的痛苦了——重复代码写得人麻木,后期改个错误提示还要到处找地方改。给你两个实用的优化方案,能帮你把重复代码砍掉一大半:

方案一:在HttpService里封装通用处理逻辑

把所有请求的成功/错误处理抽成通用函数,让每个业务请求复用,不用重复写逻辑:

angular.module('mahanApp').service('HttpService', function($http, $log) {
  // 通用成功处理器:统一提取响应数据、打日志
  function handleSuccess(response) {
    $log.info(`请求成功: ${response.config.url}`);
    return response.data; // 直接返回数据,组件层不用再取response.data
  }

  // 通用错误处理器:统一打日志、错误提示、状态码处理
  function handleError(error) {
    $log.error(`请求失败: ${error.config.url} | 状态码: ${error.status}`);
    
    // 可以根据状态码做全局处理,比如401跳登录、500提示服务器错误
    switch(error.status) {
      case 401:
        // 示例:跳转到登录页
        // $location.path('/login');
        break;
      case 500:
        // 示例:弹出全局错误提示
        // alert('服务器开小差了,请稍后重试');
        break;
      default:
        alert(`请求出错:${error.statusText}`);
        break;
    }
    // 把错误抛出去,方便组件层有特殊需求时继续处理
    return Promise.reject(error);
  }

  // 封装基础GET请求,自动绑定通用处理
  function baseGet(url, config = {}) {
    return $http.get(url, config)
      .then(handleSuccess)
      .catch(handleError);
  }

  // 业务请求:获取所有名称(直接复用基础请求)
  function getNames() {
    return baseGet('/data/names/');
  }

  // 同理可以封装POST/PUT/DELETE等方法
  function basePost(url, data, config = {}) {
    return $http.post(url, data, config)
      .then(handleSuccess)
      .catch(handleError);
  }

  return {
    getNames: getNames,
    // 也可以暴露基础方法给其他组件使用
    get: baseGet,
    post: basePost
  };
});

然后在控制器里,只需要处理当前组件的业务逻辑就行:

angular.module('mahanApp').controller('NameController', function NameController(HttpService) {
  var ctrl = this;
  ctrl.names = [];
  ctrl.loading = true;

  // 获取名称列表,只处理当前组件的成功逻辑
  HttpService.getNames()
    .then(function(data) {
      ctrl.names = data;
    })
    // 只有当前组件需要特殊错误处理时才加这个catch,否则可以省略
    .catch(function(error) {
      ctrl.errorMsg = '加载名称失败,请刷新页面重试';
    })
    .finally(function() {
      ctrl.loading = false;
    });
});
方案二:用HTTP拦截器全局统一处理

如果整个应用的请求逻辑都很统一,用拦截器可以做到全局拦截所有请求/响应,连服务里的封装都能简化:

angular.module('mahanApp').config(function($httpProvider) {
  $httpProvider.interceptors.push(function($log, $q) {
    return {
      // 请求发送前的拦截(可选:比如给所有请求加token)
      request: function(config) {
        // 示例:添加Authorization头
        // config.headers.Authorization = 'Bearer ' + localStorage.getItem('token');
        $log.info(`发送请求: ${config.url}`);
        return config;
      },
      // 响应成功拦截:统一返回data
      response: function(response) {
        $log.info(`请求成功: ${response.config.url}`);
        return response.data;
      },
      // 响应错误拦截:统一处理所有错误
      responseError: function(error) {
        $log.error(`请求失败: ${error.config.url} | 状态码: ${error.status}`);
        
        // 全局错误处理逻辑
        switch(error.status) {
          case 401:
            // 处理未授权,比如跳登录
            break;
          case 500:
            alert('服务器内部错误,请稍后重试');
            break;
        }
        return $q.reject(error);
      }
    };
  });
});

这时你的HttpService可以回到最简洁的状态:

angular.module('mahanApp').service('HttpService', function($http) {
  function getNames() {
    return $http.get('/data/names/');
  }

  return {
    getNames: getNames
  };
});
两种方案的适用场景
  • 服务封装:适合有多个业务模块,不同模块需要不同通用逻辑的情况,灵活性更高
  • 拦截器:适合整个应用的请求逻辑高度统一的场景,代码最精简,全局修改更方便

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 07:04:54