如何对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
相关产品推荐
相关产品推荐

