jquery的$ajax封装


//页面加载所要进行的操作
$(function () {
    //设置ajax当前状态(是否可以发送);
    ajaxStatus = true;
});

// ajax封装
function ajax(url, data, success, cache, alone, async, type, dataType, error) {
    var type = type || 'post';//请求类型
    var dataType = dataType || 'json';//接收数据类型
    var async = async || true;//异步请求
    var alone = alone || false;//独立提交(一次有效的提交)
    var cache = cache || false;//浏览器历史缓存
    var success = success || function (data) {
            /*console.log('请求成功');*/
            setTimeout(function () {
                layer.msg(data.msg);//通过layer插件来进行提示信息
            },500);
            if(data.status){//服务器处理成功
                setTimeout(function () {
                    if(data.url){
                        location.replace(data.url);
                    }else{
                        location.reload(true);
                    }
                },1500);
            }else{//服务器处理失败
                if(alone){//改变ajax提交状态
                    ajaxStatus = true;
                }
            }
        };
    var error = error || function (data) {
            /*console.error('请求成功失败');*/
            /*data.status;//错误状态吗*/
            layer.closeAll('loading');
            setTimeout(function () {
                if(data.status == 404){
                    layer.msg('请求失败,请求未找到');
                }else if(data.status == 503){
                    layer.msg('请求失败,服务器内部错误');
                }else {
                    layer.msg('请求失败,网络连接超时');
                }
                ajaxStatus = true;
            },500);
        };
    /*判断是否可以发送请求*/
    if(!ajaxStatus){
        return false;
    }
    ajaxStatus = false;//禁用ajax请求
    /*正常情况下1秒后可以再次多个异步请求,为true时只可以有一次有效请求(例如添加数据)*/
    if(!alone){
        setTimeout(function () {
            ajaxStatus = true;
        },1000);
    }
    $.ajax({
        'url': url,
        'data': data,
        'type': type,
        'dataType': dataType,
        'async': async,
        'success': success,
        'error': error,
        'jsonpCallback': 'jsonp' + (new Date()).valueOf().toString().substr(-4),
        'beforeSend': function () {
            layer.msg('加载中', {通过layer插件来进行提示正在加载
                icon: 16,
                shade: 0.01
            });
        },
    });
}

// submitAjax(post方式提交)
function submitAjax(form, success, cache, alone) {
    cache = cache || true;
    var form = $(form);
    var url = form.attr('action');
    var data = form.serialize();
    ajax(url, data, success, cache, alone, false, 'post','json');
}
/*//调用实例
$(function () {
    $('#form-login').submit(function () {
        submitAjax('#form-login');
        return false;
    });
});*/

// ajax提交(post方式提交)
function post(url, data, success, cache, alone) {
    ajax(url, data, success, cache, alone, false, 'post','json');
}

// ajax提交(get方式提交)
function get(url, success, cache, alone) {
    ajax(url, {}, success, alone, false, 'get','json');
}

// jsonp跨域请求(get方式提交)
function jsonp(url, success, cache, alone) {
    ajax(url, {}, success, cache, alone, false, 'get','jsonp');
}

  

在实际的项目里,ajax的应用频率很高,所以尽管jquery或者其他的一些类似的js库做了非常不错的封装,仍然有进一步封装简化的空间和必要

举一个例子,很久很久以前,我的ajax是这么写的:

复制代码
$.ajax({
  url: 'www.baidu.com/getInfo',
  type: 'POST',
  data: {
    name: 'jack',
    age: 18
  },
  dataType: 'json',
  success: function(resp){
  // callback
  },
  error: function(err){
  // error code
  }    
});
复制代码

乍一看挺好没啥问题,但是其实success回调里的逻辑可能很复杂,甚至可能会出现ajax回调里再放一个ajax的情况,那这种写法就很糟糕了,全都杂糅在一起

可以进行一个简单的封装,这在之前Deferred对象的随笔里已经有提到

复制代码
function ajax(url, param, type) {
  // 利用了jquery延迟对象回调的方式对ajax封装,使用done(),fail(),always()等方法进行链式回调操作
  // 如果需要的参数更多,比如有跨域dataType需要设置为'jsonp'等等,也可以不做这一层封装,还是根据工程实际情况判断吧,重要的还是链式回调
  return $.ajax({
    url: url,
    data: param || {},
    type: type || 'GET'
  });
}

// 链式回调
ajax('www.baidu.com/getInfo').done(function(resp) {
    // 成功回调
  }).fail(function(err) {
    // 失败回调
  });
复制代码

但是虽然做到这一步了,问题还是会来,比如我司,成功的回调里还有一层逻辑判断,像这样:

复制代码
// 我司ajax返回的json数据格式
// 当result为false时,msg中往往有错误信息
{
  result: true,
  data: {
    name: 'jack'
  },
  msg: null
}

ajax('www.baidu.com/getInfo').done(function(resp) {
    // 成功回调
    if(resp.result){
      // 当resp中result为true时的操作
      // 往往这个时候要操作处理resp中的data对象信息
    }
    else{
      // 当result为false时的操作,这时往往会根据resp中的另一属性msg来判断具体处理
    }
  }).fail(function(err) {
    // 失败回调
  });
复制代码

问题有二:

第一,我每个ajax中都需要写一个同样的相对固定的逻辑判断(每个公司或者项目组可能会有不同,但是就项目本身而言,或者放大了到公司来说必然是固定的),我觉得很烦。

第二,如果我只想专注处理数据,比如在成功回调里,我直接拿到要处理要渲染的数据,在失败的回调里我直接拿到错误的代码,有没有这样的可能做进一步的封装。

其实这俩问题是一个,总结一句话,就是不想写那么多if,else。有一句话我觉得说得很好,逻辑是守恒的,但如果是可预见的逻辑,是有精简的可能的,我们这种显然属于可预见的逻辑。

二次封装利用了延迟对象的then方法,具体看代码:

复制代码
function handleAjax(url, param, type) {
  return ajax(url, param, type).then(function(resp){
      // 成功回调
      if(resp.result){
        return resp.data; // 直接返回要处理的数据,作为默认参数传入之后done()方法的回调
      }
      else{
        return $.Deferred().reject(resp.msg); // 返回一个失败状态的deferred对象,把错误代码作为默认参数传入之后fail()方法的回调
      }
    }, function(err){
      // 失败回调
      console.log(err.status); // 打印状态码
    });
}

handleAjax('www.baidu.com/getInfo').done(function(resp){
    // 当result为true的回调
  }).fail(function(err){
    // 当result为false的回调
  });
复制代码

这就把之前很杂揉的代码进一步的的简化,也方便了维护,比如某一天跟你说result不再是布尔值了,直接改成状态码这样的东西了,如果按以前一个ajax写一个判断,简直要疯。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM