Angular最佳实践之$http-麻雀虽小 五脏俱全

原文写于 2014-10-26 https://github.com/kuitos/kuitos.github.io/issues/12

AngularJs框架为我们封装了http用于提供ajax服务,但是作为调用者而言,工程化的项目中直接调用http用于提供ajax服务,但是作为调用者而言,工程化的项目中直接调用http去发请求总是不友好且不易于拓展的。合理的做法是前后端使用统一的接口规范、restful。前端采用angular resource调用restful接口。这样才更便于前端做统一封装,将通用需求对调用者透明。

先说说对于http请求我的通用化需求有哪些:

  1. 所有的查询请求都缓存起来,并实现修改通知机制。简而言之就是对某一资源的查操作均走缓存,而在对这个资源做过修改(update、insert、delete)之后要立即告知缓存需要更新。
  2. 基于http请求响应实现的loading动画。在所有http请求未全部响应完成之前会出现loading动画,响应全部成功回来之后结束loading,而且这一切对于调用者而言应该是透明,而不是每次发请求前loading=true,如何在响应成功回调里面loading=false。这样要累死的

好在Angular给我们提供了http拦截器,减少了我们一大半工作量。so,我们只需要在拦截器中加入请求缓存及修改刷新缓存的逻辑就可以实现我们的第一个需求。具体上代码

/*** @author kui.liu* @since 2014/10/10 下午5:52* http处理器,用于设定全局http配置,包括loading状态切换,拦截器配置,超时时间配置等*/
;
(function (angular, undefined) {    "use strict";// 模拟service的私有服务var _app = {};angular.module("common.http-handler", []).config(["$httpProvider", function ($httpProvider) {/******************** http拦截器,用于统一处理错误信息、消息缓存、响应结果处理等 **********************/$httpProvider.interceptors.push(["$q", "$log", function ($q, $log) {return {response: function (res) {var config = res.config,responseBody = res.data,cache;if (angular.isObject(responseBody) && !responseBody.success) {$log.error("%s 接口请求错误:%s", config.url, responseBody.message);return $q.reject(res);} else {// 自定义配置,用于query请求直接返回data部分if (config.useDataDirect) {res.data = responseBody.data;}// 自定义配置,若该请求成功后需要重新刷新cache(save,update,delete等操作),则清空对应cache。angular默认cache为$httpif (config.refreshCache) {cache = angular.isObject(config.cache) ? config.cache : _app.cacheFactory.get("$http");cache.removeAll();}return res;}},responseError: function (res) {$log.error("%s 接口响应失败! 状态:%s 错误信息:%s", res.config.url, res.status, res.statusText);return $q.reject(res);}}}]);}]).run(["$rootScope", "$timeout", "$cacheFactory", function ($rootScope, $timeout, $cacheFactory) {/** 绑定cache服务 **/_app.cacheFactory = $cacheFactory;}]);
})(window.angular);

然后我们定义resource时只需要加入缓存,对于需要通知缓存的方法加上refreshCache(这个是自定义属性,配合http interceptor使用)标识就行:

$resource(url,{}, {"get"   : {method: "GET", cache: true},"save"  : {method: "POST", refreshCache: true},"query" : {method: "GET", isArray: true, cache: true, useDataDirect: true},"remove": {method: "DELETE", refreshCache: true},"delete": {method: "DELETE", refreshCache: true}
});

调用还是跟往常一样,一切对用户透明。只是我们查看network的时候会发现请求都会被缓存起来。比如下面这个表格
image2014-10-26 16:30:42.png
点第二页
image2014-10-26 16:31:36.png
再点回第一页
image2014-10-26 16:32:19.png
可以看到并没有http请求发出,数据是直接从缓存中响应给请求的。如果我们某个时刻修改了这条数据,那么下次查询请求的时候就不会走缓存了,而是直接从走http然后重新把结果缓存起来。具体就不演示了。
可以毫不夸张的说,如果我们一个数据交互比较频繁的页面,用户在上面操作持续时间超过3分钟,那么我们的IO数就能节省50%以上,这样不仅能大大降低服务器压力,同时前端的响应速度也会大大提升。而且这个比例会随着用户的停留时间增加而增加。最主要的是,一切对调用者都是透明的!!

再来看看我们的第二个需要。基于http请求响应的自动loading状态。实现方式大同小异,同样是利用httpProvider,只是这里用的是httpProvider,只是这里用的是http提供的transformRequest和transformResponse

/*** @author kui.liu* @since 2014/10/10 下午5:52* http处理器,用于设定全局http配置,包括loading状态切换,拦截器配置,超时时间配置等*/
;
(function (angular, undefined) {    "use strict";// 模拟service的私有服务var _app = {};angular.module("common.http-handler", []).config(["$httpProvider", function ($httpProvider) {var/** loading状态切换 */count = 0,loading = false,stopLoading = function () {count = 0;loading = false;_app.loading(false); // end loading};/*************************** http超时时间设为30s ***************************/$httpProvider.defaults.timeout = 30 * 1000;/* 广告时间哈哈.... */$httpProvider.defaults.headers.common["X-Requested-With"] = "https://github.com/kuitos";/************************* 根据http请求状态判断是否需要loading图标 *************************/$httpProvider.defaults.transformRequest.push(function (data) {  // global loading startcount += 1;if (!loading) {_app.timeout(function () {if (!loading && count > 0) {loading = true;_app.loading(true);}}, 500); // if no response in 500ms, begin loading}return data;});$httpProvider.defaults.transformResponse.push(function (data) { // global loading endcount -= 1;if (loading && count === 0) {stopLoading();}return data;});}]).run(["$rootScope", "$timeout", "$cacheFactory", function ($rootScope, $timeout, $cacheFactory) {/** 绑定timeout服务 */_app.timeout = $timeout;/** loading状态切换 **/_app.loading = function (flag) {$rootScope.loading = flag;};/** 绑定cache服务 **/_app.cacheFactory = $cacheFactory;}]);
})(window.angular);

当响应时间超过500ms(可自己设定,一般不要超过1s),则loading动画自动出现,响应成功回来后动画消失。

angular给开发者提供了一套便利的设备龚开发者使用,几乎后端mvc框架中最常用的东西它都会提供。只是angular的官方文档实在写的太烂,这也是社区一直在吐槽的点,很多时候api上并不会告诉你它那个接口的所有功能,搞不定的时候我们还是应该好好读读它那一块的源码,相信我,你总会有意外收获!
最新最详尽代码请移步:source code

Angular最佳实践之$http-麻雀虽小 五脏俱全相关推荐

  1. angular 最佳实践_干净高效的Angular应用程序的最佳实践

    angular 最佳实践 by Vamsi Vempati 由Vamsi Vempati 干净高效的Angular应用程序的最佳实践 (Best practices for a clean and p ...

  2. 2021年的Angular最佳实践

    目录 使用Angular CLI 保持最新 严格模式 使用延迟加载 取消订阅RxJS Observables 将ngFor与trackBy一起使用 结论 Angular由Google开发人员使用Typ ...

  3. angular项目打包_vue项目部署的最佳实践

    前言 使用vue.react.angular等技术开发过程中,我们都会遇到以下问题: 首屏加载慢 每一次更新都需要清除浏览器缓存才能看到效果(经常被测试吐槽) 这两个问题可以从很多方面进行优化,今天我 ...

  4. Angular应用内路由(In App Route)的最佳实践

    Angular官网里关于路由开发的最佳实践指导: In Angular, the best practice is to load and configure the router in a sepa ...

  5. 研发效能提升最佳实践的探索

    GIAC(GLOBAL INTERNET ARCHITECTURE CONFERENCE)是长期关注互联网技术与架构的高可用架构技术社区和msup推出的,面向架构师.技术负责人及高端技术从业人员的年度 ...

  6. GMTC 大前端时代前端监控的最佳实践

    摘要: 今天我分享的内容分成三个部分: 第一部分是"大前端时代前端监控新的变化", 讲述这些年来,前端监控一些新的视角以及最前沿的一些思考. 第二部分"前端监控的最佳实践 ...

  7. web前端开发最佳实践_学习前端Web开发的最佳方法

    web前端开发最佳实践 为什么要进行网站开发? (Why web development?) Web development is a field that is not going anywhere ...

  8. 《AngularJS深度剖析与最佳实践》一第1章 从实战开始

    本节书摘来自华章出版社<AngularJS深度剖析与最佳实践>一书中的第1章,作者 雪狼 破狼 彭洪伟,更多章节内容可以访问云栖社区"华章计算机"公众号查看 第1章 从 ...

  9. AngularJS 最佳实践

    AngularJS 最佳实践 2013-07-01 17:51 原文 简体 繁體 61,564 次围观 AngularJS 是一个 Web 应用框架,它实现了前端的 MVC 架构,能让开发人员很方便地 ...

  10. 《AngularJS深度剖析与最佳实践》一2.2 模块

    本节书摘来自华章出版社<AngularJS深度剖析与最佳实践>一书中的第2章,第2.2节,作者 雪狼 破狼 彭洪伟,更多章节内容可以访问云栖社区"华章计算机"公众号查看 ...

最新文章

  1. php 选择路径上传方法,PHP上传文件时自动分配路径的方法,_PHP教程
  2. Android 美团Robust热更新 使用入门
  3. code ro rw zi 编译的一个ARM的程序,编译结果中的一句话
  4. snakeyaml读取yaml/yml配置文件数据
  5. .NET Core MVC扩展实践
  6. 为什么计算机语言都是英语,编程为什么都是英语 编程为什么没有汉语
  7. hbase 命令_HBase原理与实践 | 生产环境上线前真的优化过吗?
  8. 【 Codeforces Round #395 (Div. 2) D】Timofey and rectangles【四色定理】
  9. vue 对象提供的属性功能、通过axio请求数据(2)
  10. 关于ztree的使用
  11. 对话仟峰资本Steven:DeFi大赢家是怎样炼成的 |链捕手
  12. 计算机视觉算法面试准备
  13. Python数据分析基础技术之scikit-learn(史上最全面)
  14. 各个键盘按键KeyValue值
  15. 容器亲和、反亲和、污点、容忍以及驱逐的介绍
  16. QQ看点模块100条测试用例
  17. 使用python中的Selenium爬取百度文库word文章
  18. Big Faceless Applet PDF阅读器
  19. 2023年4月应急预案演练、应急处置知识
  20. 国际歌 英特纳雄耐尔一定要实现

热门文章

  1. 基于 SpringBoot + MyBatis-Plus 的公众号管理系统,接私活必备!
  2. 网吧服务器怎么加无线路由器,网吧有线路由器接无线路由该如何设置?
  3. 广西壮族自治区公安厅信息中心异地容灾系统(三期)采购185万
  4. 怎么看神经网络过早收敛_你的神经网络真的收敛了么?
  5. 各双拼输入方案之间有明显的优劣之分吗?
  6. Windows 10, version 21H2 (released Nov 2021) 简体中文版、英文版(企业版)下载
  7. 混沌算法 matlab,混沌算法优化BAS算法
  8. vue项目中金额小写转换为汉字大写的功能封装
  9. android自定义键盘 下划线,TabLayout 自定义下划线
  10. 手机短信校验(前端js)