在中大型的前端应用里面项目里面一般包夹了大量的ajax请求,一般状况这些请求夹杂在业务代码里面,拓展维护的成本比较大。php
如要改整个项目的url前缀(后端把接口路径统一加个assets或者http换成https),或者要改请求的类型get换post,亦或者统一加个CSRFToken,咱们该当如何,手动一个个把本身一头扎进业务代码里面去修改吗?html
此时不妨试试用一个js去统一管理这些ajax请求。前端
如下是咱们使用ajax请求的方式node
调用请求的时候拼装url,在较多ajax请求的时候面,维护拓展就变得很是的艰难
本文章想法是把url抽象成不一样类型的参数react
公共型参数: 每一个url都共用的部分 如http类型,url前缀,mockurl前缀,token等jquery
配置型参数: 每一个url都不同的,但能够提早预知的部分,如uri地址,ajax请求方式(get/post)git
业务型参数: 具体进业务场景方能算出来的参数 如test=xxx(xxx的值只有程序运行的时候才知道值)github
公共型参数和配置型参数能够在项目初始化的时候经过逻辑控制并存起来,
业务型参数在具体调用的时候在具体的业务场景获取。
在经过统一的ajax请求获取资源ajax
统一的ajax请求,能够在失败以后,统一抛出异常,成功以后统一改变获取数据的结构等等好处json
简单工程建立 参数实例,并将实例对象存储在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,$);
db.js 负责注册ajax请求,并全局的设置url前缀,是否启用mockurl,对不一样请求配置不一样的请求方式,是否jsonp等
(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', { get: { type: 'GET', url: 'getMySimpleInfo.json', once: true } }); window.DB = DBF.context; })(window.DBFactory);
ajax的真正调用者,经过DB.xxx 拿到参数对象后以get的形式触发实际的ajax请求,并附带业务代码里面的参数。
$(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 返回成功
promise2 拿getMySimpleInfo.json 资源未获取到,返回失败
本篇文章是以jquery形式展现的,但稍事修改也是能够在backbone,react等框架内使用。
测试代码及源码下载在https://github.com/laughing-p... 中