如何更有效的在中大型项目中管理ajax请求
前言在中大型的前端应用里面项目里面通常包夹了大量的ajax请求,通常情况这些请求夹杂在业务代码里面,拓展维护的成本比较大。 如要改整个项目的url前缀(后端把接口路径统一加个assets或者http换成https),或者要改请求的类型get换post,亦或者统一加个CSRFToken,我们该当如何,手动一个个把自己一头扎进业务代码里面去修改吗? 此时不妨试试用一个js去统一管理这些ajax请求。 分析以下是我们使用ajax请求的方式 调用请求的时候拼装url,在较多ajax请求的时候面,维护拓展就变得非常的艰难 将url分为三类:
公共型参数和配置型参数可以在项目初始化的时候通过逻辑控制并存起来, 流程图
统一的ajax请求,可以在失败之后,统一抛出异常,成功之后统一改变获取数据的结构等等好处 代码实现简单工厂存储url参数对象简单工程创建 参数实例,并将实例对象存储在context内部 (function (root,$) { //简单工厂生成项目统一的ajax参数对象 var DBFactory = { __: {},//可有业务代码设置mockUrl,prefixUrl等 set: function (key,value) { this.__[key] = value; },get: function (key) { return this.__[key]; },create: function (name,methods) { // 禁止创建重名的DB实例 if (this.context[name]) { console.warn('DB: "' + name + '" is existed! '); return; } return this.context[name] = new DB(name,methods); },// 存储db实例 context: { } }; //DB构造函数 负责构造ajax参数对象 function DB(DBName,methods) { var t = this; t.cache = {}; $.each(methods,function (method,config) { if (typeof config === 'function') { t[method] = config; return; } t[method] = function (query) { var cfg = {}; cfg.method = method; cfg.DBName = DBName; cfg.mockUrl = config.mockUrl; // 如果设置了`mock`代理 if (cfg.mockUrl && typeof DBFactory.__.mockProxy === 'function') { cfg.mockUrl = DBFactory.__.mockProxy(cfg.mockUrl); } //合并参数 cfg.query = $.extend({},config.query || {},query || {}); //判断是否mock cfg.isMock = config.url ? false : true; //url前缀供getUrl计算url t.urlPrefix = DBFactory.get('urlPrefix') || ''; //url cfg.url = cfg.isMock ? cfg.mockUrl : (t.getUrl(config.url) || cfg.mockUrl); // 是否是全局只获取一次 cfg.once = typeof config.once === 'boolean' ? config.once : false; // 数据缓存,如果`once`设置为true,则在第二次请求的时候直接返回改缓存数据。 t.cache[method] = t.cache[method] || null; cfg.jsonp = config.jsonp || false; cfg.type = config.type || 'POST'; return request(cfg,t); }; }); } /** * 获取正式接口的完整`url` * 如果通过`DB.set('urlPrefix','https://xxx')`设置了全局`url`的前缀,则执行补全 */ DB.prototype.getUrl=function (url) { if (this.urlPrefix && url.indexOf('http') !== 0 && url.indexOf('//') !== 0) { return this.urlPrefix + url; } else { return url; } }; /** * * @param cfg 属性对象提供给ajax修改请求属性 * @param db db提供缓存 * @returns ajax promise */ function request(cfg,db) { var defer = $.Deferred(); if (cfg.once && db.cache[cfg.method]) { defer.resolve(db.cache[cfg.method]); } else { var ajaxOptions = { url: cfg.url,data: cfg.query,success: function (resp) { //cfg.once && (db.cache[cfg.method] = resp); defer.resolve(resp); },error: function (error) { defer.reject({ fail:true,msg: error }); } }; if (cfg.jsonp === true) { ajaxOptions.dataType = 'jsonp'; } else { ajaxOptions.dataType = 'json'; ajaxOptions.type = cfg.type; } $.ajax(ajaxOptions); } return defer.promise(); }; root.DBFactory = DBFactory; })(this,$); 配置参数
(function (DBF) { var isOnline = false; // 设置全局的`url`前缀 var urlPrefixForLocal = location.protocol + '//' + location.host+'/'; if (!isOnline) { DBF.set('urlPrefix',urlPrefixForLocal); } else { DBF.set('urlPrefix','/trs'); } // MockProxy mock 数据服务器(node/php代理)代理,以跨过同源检测 DBF.set('mockProxy',function (mockUrl) { return '/mock?url=' + mockUrl }); DBF.create('Test',{ get: { type: 'GET',// jsonp: true,url: 'example/ajax-data/data.json' // mockUrl: urlPrefixForLocal + '/ajax-data/data.json',//once: true } }); DBF.create('GetPersonInfo',url: 'getMySimpleInfo.json',once: true } }); window.DB = DBF.context; })(window.DBFactory); 开始测试加上请求的资源
调用代码
$(document).ready( function () { var DB = window.DB; var promise1 = $.when(DB.Test.get({test: true})); var promise2 = $.when(DB.GetPersonInfo.get()); promise1.then( function (res) { console.log(res) $('#promise1').html('promise1:'+res.data); },function (error) { console.log(error); }); promise2.then( function (res) { console.log(res) },function (error) { $('#promise2').html('promise2:'+error.msg.responseText); }); } ) 运行结果promise1 拿data.json 返回成功
本篇文章是以jquery形式展示的,但稍事修改也是可以在backbone,react等框架内使用。 归纳本篇文章是通过对ajax请求调用前,调用后的统一处理来更有效的控制这些请求,类似于面向切面的思想。(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |