集中式ajax配置管理方案

大家好,我是入错行的bug猫。(http://blog.csdn.net/qq_41399429,谢绝转载)

本文主要解决大型项目中,海量ajax的统一管理方法

公司所做的产品系统,均是严格意义上的前后端分离,数据交换全部通过ajax+json完成。

页面上大量地使用到ajax,在后续产品迭代过程中,如果需要修改一些关于ajax底层东西:比如修改超时配置、调整加载过程中的图片、url地址调整、后台系统换地址、统一风格的异常提示等等。假设没有一个集中管理方案,这些改动简直是灾难!

一般解决方案是,在一些框架(jquery、angular、vue)的ajax基础之上,做一次封装,创建一个全局的ajax对象等。总之,在做前端规划的时候,肯定会意识到,必须要有一个高可复用、或者统一的ajax请求方法。


作为一个专业的前端,bug猫其实不想关注ajax调用的地址是多少、如果发生了http异常*(400、404、500、505)*之后要怎么做、如果发生了业务异常怎么处理、用户未登录异常、token超时异常等等这很low的东西!

如果每发起一个ajax请求,bug猫都要做这一系列的判断,那么bug猫肯定陷入了无限加班凄惨的命运QwQ
bug猫只想关注页面做得怎么绚丽、ajax的入参是什么、正常返回的报文是什么!
还有开发环境的后台地址是一个,测试环境、正式环境的地址是另外一个,有时甚至还要连后台开发人员的地址。
总之,bug猫也不想总是ajax的ip地址换来换去!还有隔壁同事偶尔把ip地址修改之后,忘记改回来提交了…

bug猫在此决定开源自己写的一个框架,集中式ajax配置管理
所以跟着bug猫的思路来,了解集中式ajax配置管理是怎么解决上述问题的!


集中管理设计:

每一个ajax请求,看似都是各自独立、没有任何联系,但是仔细分析可以得出一些共性:

  • 都需要请求地址
  • 都有请求参数(没有请求参数按空字符串处理)
  • 都有请求方式(get|post|jsonp)
  • 都有请求成功后执行方法(没有按空方法处理)
  • 请求失败后执行方法(没有按制定的默认行为处理)

如果仅以请求地址为维度*(不包括get请求url上的参数、和通过url传递参数的情况)*,那么系统中所有的ajax请求都能穷举出来。
因此可以将每一个ajax请求,预置为一个函数:里面封装好url、请求方式、同步异步、是否需要加载动画,统一调用公共的异常处理方案,等等
执行这个函数,传入入参、业务处理成功后的函数、业务处理失败后的函数,等价于发起这个ajax请求。

对于前端开发而言,只需要执行这些预置函数,传入指定参数即可。

eg:传统ajax方案:

$http({url: host + "/1.0.0/login", method: "post", data:{xxx}})
.then(function(resp){
     //需要判断ajax是否请求成功、业务是否处理成功还是失败
});

//或者:
$http.post(host + "/1.0.0/login", {xxx})
.success(function(resp){
    //成功之后执行的方法。
    //其中,业务处理失败,是算成ajax请求成功、还是属于ajax请求失败,需要根据后台框架决定,判断逻辑是放在success、还是error方法里面
}).error(function(err) {  
    //http异常后的方法 
});

注:ajax请求成功,业务处理失败:比如发起订单取消,后台系统处理之后,发现订单因某种原因不可以取消。那么处理结果成功返回到前端,就属于ajax请求成功,业务处理失败。

集中式管理方案:

//预置ajax函数
//用户登录
//param:入参
//success:业务处理成功之后执行的方法,
//error:业务处理失败之后执行的方法,可以省略
function userLogin(param, success, error){
    //预置函数体
    //处理:具体访问地址、请求方式、http异常(400,404,500,304)处理、同步异步、是否需要加载动画、默认的业务处理失败之后执行方案
}

//使用时,不需要关注具体访问地址、请求方式、http异常(400,404,500,304)处理、同步异步、是否需要加载动画。
//这些配置全部在预置ajax函数中,已经配置好了
userLogin({xxxx}, function(resp){
    //业务处理成功之后执行的方法
}, function(resp){
    //业务处理失败之后执行的方法,可以省略
});

在所有需要使用用户登录的地方,直接执行userLogin即可,保证了代码的复用性,和简洁!

代码结构示意图:

       应用层             ──── 应用层关注入参、业务处理,调用预置函数
         │
         │
      预置函数            ──── 预置ajax函数,根据配置,调用$get、或者$post、或者$jsonp
         │
  ┌──────┼──────┐
  │      │      │
$get   $post  $jsonp     ──── 根据配置,在函数中追加配置:同步异步、是否需要加载动画、请求超时,调用基层_ajaxSend
  │      │      │
  └──────┼──────┘
         │
     _ajaxSend           ──── 公共的处理:http异常(400,404,500,304)处理、加载动画、默认的业务处理失败之后执行方案
         │
         │
       $http             ──── 这一层负责发起ajax请求,具体实现代码无需关注,甚至不是angular的$http,是juqery的$.ajax都无所谓

看似很美好,但是!!!!!!!!

一个稍微大型的管理系统,ajax的数量可能会达到上千!

即便我们能不辞辛劳地为每一个ajax设置一个预置函数,
但是,这样会导致在页面加载之后,会出现上千个函数!

会不会影响性能、会不会造成浏览器露出底裤,bug猫没有测试过,
但是要写上千个函数,bug猫从来都没想要干过!

要是有一个方法,可以在需要某个预置函数的时候,能动态生成它就好了!
嗯,简单来说,就是根据配置,动态生成一个函数!

上千个预置函数,要想指定动态生成某一个,至少要给每个预置函数起个名字吧!
但是又会出现操蛋的命名冲突!方案有隐患,pass!

上述说到的,每个ajax预置函数,至少有请求地址、请求方式两项配置,我们可以把配置声明成为一个对象,存放到一个"仓库"里面,
给函数取名会有命名冲突,我们给配置取名称,总行了吧?

给配置加上不同的命名空间:将"仓库"按照功能模块,分成不同的"容器",容器里面可以再放"容器",也可以直接放配置。

//ajax配置
var configs = {
     //登录注册模块
     login : {
         //登录ajax配置
         userLogin:{url:"xxx", method:"post"},

         //退出ajax配置
         logout : {url: "xxx", method: "get", loading:"0"},
     },
     //个人中心模块
     home : {
         
     },
     //商品模块
     goods : {
     
     },
}

现在ajax配置有自己的名字了,那预置函数的名字……?
还有存在的必要吗?因为预置函数,是实时通过ajax配置生成的,在同一时刻只可能存在一个。

我们假设有一个"工厂",可以根据configs.xxx.xxx生产不同的预置函数,并且将其返回到应用层,

           ajax配置                 返回
应用层  ─────────────────> 工厂  ────────────> 预置函数

configs是全局的配置,如果在表现层能直接获取到configs的引用,是十分危险的!
危险的东西必须隐藏起来!

//通过ajax配置命名空间,获取ajax配置
//operId:ajax配置的命名空间,示例:"login.userLogin","login.logout",全部基于configs对象
//configs:configs对象
var getValues = function(operId, configs) {
    var operIds = operId.split("."), obj = configs;
    for(var i = 0, l = operIds.length; i < l; i++) {
        var key = operIds[i];
        obj = obj[key];
    }
    return obj;
}

现在只有单个的ajax配置对象,返回给了应用层。
不行,还是危险,需要再次封装!

而且,当有发起多个ajax请求,要求在这些ajax执行完毕之后,在执行某些操作的应用场景,
angular、jquery、VUE等框架,都有配套的方法,

因此bug猫的集中式ajax管理框架中也不能少!


上代码,以angular框架为例:

page1

/**
 * 注册三个对象,分别为开发、测试、线上环境相关的配置
 * */
app.constant("devconfig", {apiurl :"http://192.168.3.90:8070"})
   .constant("testconfig", {apiurl : "http://测试环境地址"})
   .constant("prodconfig", {apiurl : "http://线上环境地址"});

page2


/**
 * 注册一个名为$conn的服务,依赖$http,和环境配置("devconfig")
 * 在打包的时候,将"devconfig"字符串,替换成page1中对应的环境名称
 * $http:angular的$http服务
 * devconfig:依赖注入的环境配置
 * */
app.factory("$conn",["$http","devconfig",function($http,conf){
    
    
    //从环境配置中获取后台服务地址
    //如果在本地需要修改后台地址,在page1中修改,禁止开发人员修改 "devconfig",和apiurl的值
    //通过svn、或者git禁止page1提交,这样可以防止开发人员误将配置文件提交
    var apiurl = conf.apiurl;
    
    
    //所有的ajax都在configs对象中集中配置
    var configs = {
        
        //登录注册模块
        login : {
            //此处为ajax的配置, url:请求的地址,method:请求方式 get(键值对)|post(键值对)|jsonp(json字符串)
            //还可以有其他的额外配置,比如超时、是否需要加载动画、同步异步等等
            login : {url: apiurl + "/1.0.0/login", method: "jsonp"},        //登录
            logout : {url: apiurl + "/1.0.0/logout", method: "get"},        //退出
            register:{url: apiurl + "/1.0.0/userRegister",method: "jsonp"}, //注册
        },
        
        //个人中心模块
        home : {
            editPwd: {url: apiurl + "/1.0.0/vipEmpEditPwd",method: "jsonp"},//修改密码
        },
        
        //商品模块
        goods : {
            
        },
        
        //此处模块下,可以有多级子模块
    };
    
    //factory返回对象
    var conn = {};
    
    
    //公共的默认参数
    var defaults = {
        //请求头文件
        headers: {},    
        
        timeoutError: function(msg) {
            msg = msg || "服务器失去响应,请刷新后重新尝试!";
            swal.error(["似乎网络开小差了", msg]);  //公司的ui,不用在意
            conn.overlayHide();     //隐藏加载动画
        },
        httpError: function(msg) {
            msg = msg || "您当前网络不畅,请刷新后重新尝试!";
            swal.error(["似乎网络开小差了", msg]);
            conn.overlayHide();
        },
        businessError: function(tips) {
            tips = tips || "";
            swal.error(["系统出错了,请刷新后重新尝试!", tips]);
            conn.overlayHide();
        }
    };  
    
    //加载动画
    var overlay = {};
    
    //正在执行的ajax次数
    //如果同时发起了多个ajax请求,那么应该在最后一个ajax结束之后,才隐藏加载动画
    overlay.overlayCount = 0;
    
    //显示遮罩层,每发起一个ajax请求,都要执行该方法
    //ajaxConf:为ajax配置对象
    overlay.layerOverlayShow = function(ajaxConf) {
        //如果在ajax配置中,设置的loading=1、或者为undefined,表示在执行ajax过程中,需要加载动画,
        ajaxConf.loading = !ajaxConf.loading ? "1" : "0";
        //计算器加一,并且显示加载动画
        if(ajaxConf.loading == "1"){
            overlay.overlayCount ++ ;
            $("#layerOverlay:first").show();
        } 
    };     
    
    //隐藏遮罩层,每个ajax执行完毕之后,都要执行该方法
    //ajaxConf:为ajax配置
    overlay.layerOverlayHide = function(ajaxConf) {
        
        //如果在ajax配置中,设置的loading=1,表示在执行ajax过程中,需要加载动画
        //在ajax结果返回之后,计算器减一
        if(ajaxConf.loading == "1"){
            overlay.overlayCount -- ;
        }
        
        //当计算器为0时,表示所有的ajax都返回结果了,隐藏加载动画
        if( overlay.overlayCount <= 0 ){
            overlay.overlayCount = 0;
            $("#layerOverlay:first").hide();
        }
        
    };
    
    
    
    
    /**
     * 使用get方式,发送键值对
     * $http:angular的$http服务
     * url:请求地址
     * param:请求参数,支持"&key=value&k=v"字符串,也支持对象
     * success:ajax执行成功,并且业务执行成功之后,执行的方法
     * error:ajax执行成功,但是业务处理失败之后,执行的方法;如果不传入,默认执行 defaults.businessError
     * ajaxConf:传入的ajax配置对象
     * */
    var $get = function($http, url, param, success, error, ajaxConf) {
        //设置ajax的请求头
        var headers = angular.extend({}, defaults.headers);
        headers["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
        
        var _ajax = {
            url: url,
            method: "get", //"get|post|jsonp"
            headers: headers,
        };
        
        var param = param || "";
        if(typeof(param) == "string") {
            url = url + param;
        } else {
            _ajax.params = param;
        }
        _ajax.url = url;
        
        _ajaxSend($http, _ajax, success, error, ajaxConf);
    };
    
    /**
     * 使用post方式,发送键值对
     * $http:angular的$http服务
     * url:请求地址
     * param:请求参数对象
     * success:ajax执行成功,并且业务执行成功之后,执行的方法
     * error:ajax执行成功,但是业务处理失败之后,执行的方法;如果不传入,默认执行 defaults.businessError
     * ajaxConf:传入的ajax配置对象
     * */
    var $post = function($http, url, param, success, ajaxConf) {
        //设置ajax的请求头
        var headers = angular.extend({}, defaults.headers);
        headers["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
        
        param = param || {};
        var _ajax = {
            url: url,
            method: "post", //"get|post|jsonp"
            headers: headers,
            params: param
        };
        _ajaxSend($http, _ajax, success, error, ajaxConf);
    };
    
    /**
     * 使用post方式,发送json字符串
     * $http:angular的$http服务
     * url:请求地址
     * param:请求参数对象,支持json字符串
     * success:ajax执行成功,并且业务执行成功之后,执行的方法
     * error:ajax执行成功,但是业务处理失败之后,执行的方法;如果不传入,默认执行 defaults.businessError
     * ajaxConf:传入的ajax配置对象
     * */
    var $jsonp = function($http, url, json, success, error, ajaxConf) {
        //设置ajax的请求头
        var headers = angular.extend({}, defaults.headers);
        headers["Content-Type"] = "application/json;charset=utf-8";
        
        json = json || "";
        if(!!json && typeof(json) !== "string") {
            json = JSON.stringify(json);
        }
        var _ajax = {
            url: url,
            method: "post", //"get|post|jsonp"
            headers: headers,
            data: json
        };
        _ajaxSend($http, _ajax, success, error, ajaxConf);
    }
    
    /**
     * 发送ajax
     * */
    var _ajaxSend = function($http, _ajax, success, error, ajaxConf) {
        
        //ajaxConf.beforeFun:在执行ajax之前执行的方法,如果该方法返回false,则阻止ajax
        if(typeof(ajaxConf.beforeFun) == "function" && ajaxConf.beforeFun(_ajax) === false) {
            return false;
        }
        
        //在ajax请求头中,追加token
        _ajax.headers.token = window.sessionStorage.getItem("token") || "";     
        
        //默认超时时间 60s
        _ajax.timeout = ajaxConf.timeout || 60000;  
        
        //显示遮罩层
        overlay.layerOverlayShow(ajaxConf); 
        //使用angular的$http发起请求
        $http(_ajax).then(function(resp) {
            
            //关闭遮罩层
            overlay.layerOverlayHide(ajaxConf);
            
            //ajaxConf.thenBefore:在ajax返回结果之后,立即执行(优先success、error执行)。如果该方法返回false,则立即结束
            if(typeof(ajaxConf.thenBefore) == "function" && ajaxConf.thenBefore.call(this, resp, _ajax) === false) {
                return false;
            }
            
            //http请求成功,正常返回
            if(!!resp && resp.status == 200) {
                if(resp.data.errCode == 1) {//公司定义,errCode=1表示业务处理成功,其他表示失败
                    success = success || noop;
                    success(resp.data);
                } else if(resp.data.errCode == 3901 || resp.data.errCode == 4001) {
                    swal.error("登录会话已失效,请重新登录!", function() {
                        window.location.href = "/#/access/signin";
                    });
                } else if(resp.data.errCode == 3902) {
                    swal.warning("无权限访问!");
                } else if(resp.data.errCode ==  3003){
                    swal.error(["参数不合法", resp.data.errMsg]);
                } else { //业务处理异常
                    if(!!error && typeof(error) == "function") {//如果没有传入error方法,则执行默认的defaults.businessError
                        error(resp.data);
                    } else {
                        defaults.businessError(resp.data.errMsg);
                    }
                }
            } else { //http 异常
                defaults.httpError();
            };
            
            //ajaxConf.thenAfter:在执行完success、或error方法之后执行
            if(typeof(ajaxConf.thenAfter) == "function" && ajaxConf.thenAfter.call(this, resp, _ajax) === false) {
                return false;
            }
            
        }, function(resp) {//超时异常
            //关闭遮罩层
            overlay.layerOverlayHide(ajaxConf);
            if(typeof(ajaxConf.httpError) == "function" && ajaxConf.httpError.call(this, resp, _ajax) === false) {
                return false;
            }           
            defaults.timeoutError();
        });
    };
    
    
    
    
    
    
    
    
    /**
     * 通过ajax配置命名空间,获取ajax预置函数
     * operId:ajax配置命名空间,示例:"login.userLogin","login.logout",全部基于configs对象
     * uerConf:自定义配置,虽然有预置配置,但是不保证没有fuck的个性化配置,key省略不传
     * */
    conn.getConn = function(operId, uerConf) {
        var operIds = operId.split(".");
        return creart(getValues(operIds, configs), uerConf);
    }  
    
    
    // 应用场景:当有发起多个ajax请求,要求在这些ajax执行完毕之后,在执行某些操作
    // 参数:ajaxfun.lay, ajaxfun.lay, ajaxfun.lay, ..., lastdo
    // 每个 ajaxfun.lay 都是独立的,有自己独立的回调函数
    // lastdo是这些ajax都执行完毕之后,才执行的函数,入参是按ajaxfun.lay的排列顺序,返回的结果集组成的数组
    conn.when = function() {
        var args = [].slice.call(arguments);
        var argsCount = args.length - 1,
            lastdo = args[argsCount],
            resps = new Array(argsCount);
        for(var i = 0, l = argsCount; i < l; i++) {
            var lay = args[i];
            var thenAfter = lay.thenAfter || $.noop;
            lay.thenAfter = (function(resps, i) {
                return function(){
                    thenAfter.apply(this, arguments);
                    resps[i] = arguments[0];
                    argsCount--;
                    if(argsCount <= 0) {
                        lastdo.apply(this, resps);
                    }
                 }
            })(resps, i);
            lay.send();
        }
    }    
    
    
    
    /**
     * 通过ajax配置命名空间,获取ajax配置
     * */
    var getValues = function(operIds, configs){
        var obj = configs;
        for(var i=0,l=operIds.length;i<l;i++){
            var key = operIds[i];
            obj = obj[key];
        }
        return obj;
    }   
    
    //仅创建ajax预置对象
    function onlyLay(ajaxfun, param, success, error, beforeFun, thenBefore, thenAfter) {
        return {
            param: param,
            success: success,
            error: error,
            beforeFun: beforeFun,
            thenBefore: thenBefore,
            thenAfter: thenAfter,
            send: function() {
                ajaxfun(this.param, this.success, this.error, this.beforeFun, this.thenBefore, this.thenAfter);
            }
        }
    }
    
    /**
     * 根据配置,创建ajax预置函数
     * option:ajax配置
     * uerConf:自定义配置
     * */
    var creart = function(option, uerConf) {
        
        var method = option.method.toUpperCase();
        
        //ajax预置函数
        var fun = null;
        
        //get请求
        if(method == "GET") { 
            //闭包,立即执行返回一个ajax预置函数
            fun = (function(o) {
                /**
                 * ajax预置函数
                 * param:入参
                 * success:业务处理成功
                 * error:业务处理失败
                 * beforeFun:在执行ajax之前执行的方法,如果该方法返回false,则阻止ajax,可忽略不传
                 * thenBefore:在ajax返回结果之后,立即执行(优先success、error执行)。如果该方法返回false,则立即结束,可忽略不传
                 * thenAfter:在执行完success、或error方法之后执行,可忽略不传
                 * */
                var ajaxfun = function(param, success, error, beforeFun, thenBefore, thenAfter) {
                    uerConf = $.extend(uerConf, {
                        "beforeFun": beforeFun,
                        "thenBefore": thenBefore,
                        "thenAfter": thenAfter,
                        "loading": o.loading,
                        "timeout": o.timeout
                    });
                    $get($http, o.url, param, success, error, uerConf);
                };
                //仅创建ajax预置函数对象,配合conn.when方法
                ajaxfun.lay = function(param, success, error, beforeFun, thenBefore, thenAfter) {
                    return onlyLay(ajaxfun, param, success, error, beforeFun, thenBefore, thenAfter);
                }
                /**
                 * 最终返回到应用层的预置函数,应该是这样:ajaxfun(xxx)和ajaxfun.lay(xxx)包含两种方法,
                 * 第一种方法执行之后,生成ajax预置函数,可以直接执行,然后立即发起ajax请求;
                 * 第二种仅生成ajax配置对象,不可以执行。需要手动执行对象的send方法才会发起请求,一般配合conn.when方法使用
				 * */
                return ajaxfun;
            })(option);
        } else if(method == "JSONP") { //post方式,发送json对象/json字符串。在Controller中,使用@RequestBody封装成对象
            fun = (function(o) {
                var ajaxfun = function(json, success, error, beforeFun, thenBefore, thenAfter) {
                    uerConf = $.extend(uerConf, {
                        "beforeFun": beforeFun,
                        "thenBefore": thenBefore,
                        "thenAfter": thenAfter,
                        "loading": o.loading,
                        "timeout": o.timeout
                    });
                    $jsonp($http, o.url, json, success, error, uerConf);
                };
                //仅创建ajax对象
                ajaxfun.lay = function(json, success, error, beforeFun, thenBefore, thenAfter) {
                    return onlyLay(ajaxfun, json, success, error, beforeFun, thenBefore, thenAfter);
                }
                return ajaxfun;
            })(option);
        } else if(method == "POST") { //post方式,发送json对象,在Controller中,直接使用对象/键 接收
            fun = (function(o) {
                var ajaxfun = function(param, success, error, beforeFun, thenBefore, thenAfter) {
                    uerConf = $.extend(uerConf, {
                        "beforeFun": beforeFun,
                        "thenBefore": thenBefore,
                        "thenAfter": thenAfter,
                        "loading": o.loading,
                        "timeout": o.timeout
                    });
                    $post($http, o.url, param, success, error, uerConf);
                };
                //仅创建ajax对象
                ajaxfun.lay = function(param, success, error, beforeFun, thenBefore, thenAfter) {
                    return onlyLay(ajaxfun, param, success, error, beforeFun, thenBefore, thenAfter);
                }
                return ajaxfun;
            })(option);
        }
        return fun;
    };    
    
    return conn;
    
}]);


page3

//将page2依赖注入到应用层
app.controller('bugCatCtrl', ["$scope", "$http", "$conn", function($scope, $http, $conn) {
 
    var userLogin = $conn.getConn("login.login");
    userLogin({userName:"bugCat","paswd":"bugCat123"},function(resp){
        //登录成功
    });
     
 
    var logout = $conn.getConn("login.logout");
    userLogin("",function(resp){
        //退出成功
    },function(resp){//业务处理失败方法,可以省略
        //退出失败
    });


    var demo1 = $conn.getConn("xxx.xxx", {
        "beforeFun":function(ajax){
            console.log(ajax.param);
            console.log("在发起ajax之前执行,如果返回false,ajax不会执行");
            return false;
        },
        "thenBefore":function(){
            console.log("在success、error之前执行,如果返回false,success、error都不会执行");
            return false;
        },
        "thenAfter":function(){
            console.log("在success、error之后执行");
        },
        loading:0   //不需要加载动画
    });
    
    demo1({},function(resp){
        console.log("我是业务处理成功后执行方法");
    },function(resp){
        console.log("我是业务处理失败后执行方法");
    });
    
    demo1({},function(resp){
        console.log("我是业务处理成功后执行方法");
    },function(resp){
        console.log("我是业务处理失败后执行方法");
    },function(ajax){
        console.log(ajax.param);
        console.log("在发起ajax之前执行,如果返回false,ajax不会执行。会覆盖beforeFun");
        return false;	    
    }function(resp){
        console.log("在success、error之前执行,如果返回false,success、error都不会执行。会覆盖thenBefore");
    }function(resp){
        console.log("在success、error之后执行。会覆盖thenAfter");
    });



    var demo2 = $conn.getConn("xxx.xxx");
    var demo3 = $conn.getConn("xxx.xxx");
    var demo4 = $conn.getConn("xxx.xxx");

    $conn.when(
        demo2.lay({}),
        demo3.lay({"p":"1"},function(resp){
            console.log("我是业务处理成功后执行方法");
       }),
       demo3.lay({"p":"2"},function(resp){
           console.log("我是业务处理成功后执行方法");
       }),
       demo4.lay("",function(resp){
           console.log("我是业务处理成功后执行方法");
       }),
       function(respArr){
           console.log("我是上述ajax都执行之后,再执行的方法");
           console.log(respArr);
       }
   );

}]);

应用层变得简洁多了,基本上在configs中配置完毕后,满足90%的地方使用!
个别ajax,可以通过conn.getConn("", {});的第二个参数做适配。

换到jquery框架、或者vue下,同样需要将page1page2分开。
page2通过模块加载、或者通过全局对象,引入page1的环境配置。

只需要根据框架,调整$get$post$jsonp_ajaxSend方法,表现层完全不需要做任何修改!
如果后台框架返回的报文格式变了,只需要修改_ajaxSend方法中,判断业务成功、业务失败的代码!




结束语

项目地址:https://gitee.com/qq283365011/WebAP5
这是bug猫和同事做的一个开源项目,里面就用到了ajax集中管理模式,有兴趣的可以试试。






~THE END~






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值