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