對jQuery ajax jsonp的理解和使用實例

目前主流的前端跨域請求方式有兩種,一種是XHR2 CORS,也就是在服務端填上響應頭:
header(“Access-Control-Allow-Origin:*”);
/星號表示所有的域都可以接受,/
header(“Access-Control-Allow-Methods:GET,POST”);

CORS不支持ie10以下。但是

第二種是更加方便的就是jsop了,jsop有很多種實現方式,除了原生的 js script jsop之外,其他支持jsop的框架也都能完成。我今天主要就是講一講自己在使用jquery jsop時碰到的坑以及jquery ajax和jquery jsop 的區別。

首先請看我的demo:

//ajax方法
function total_tendency() {
      $.ajax({
          url: "/count/storage/data?callback=storageSurvey",
          dataType: "jsonp",  //指定服務器返回的數據類型爲jsonp
          type: "GET", 
          async:true,  
          jsonp: "callback", ///指定參數名稱,默認爲callback  
          jsonpCallback:"storageSurvey", //指定回調函數名稱
          success: function (data) {
                   storageSurvey_local(data);
          },
          error:function () {
            alert("error");
    }
}


function storageSurvey_local(data) {
    //將後臺返回的數據先進行base64解碼,再轉換成json格式。
    function decode(rtnData){
                  var dstr = kvcommon.base64Decode(rtnData);
                  var rtnData = kvcommon.Ajax.Str2Json(dstr);
                  return rtnData;
              }
              var now_data = decode(data);
              var json = now_data[0];
              console.log(now_data);
              if(json.status == 0) {
                   var length = json.len;
                     modules = {};
                  //數據渲染
                   var modules = json.storage;
                  var max_count = json.max_count;
                  //在model_add()這個方法裏進行數據獲取和渲染
                   model_add(length,modules,max_count);

              }
}

在total_tendency( )這個函數裏的ajax中我使用的ajax裏可以看到,所有加了註釋的地方都是與普通ajax傳json數據不一樣的地方。
只有這些不同嗎?當然不是的,網上很多都說ajax和jsop不能歸結爲一種東西,事實上也正是如此,爲什麼這麼說?請看如下代碼:

//ajax方法
function total_tendency() {
      $.ajax({
          url: "/count/storage/data?callback=storageSurvey",
          dataType: "jsonp",  //指定服務器返回的數據類型爲jsonp
          type: "GET", 
          async:true,  
          jsonp: "callback", ///指定參數名稱,默認爲callback  
          jsonpCallback:"storageSurvey", //指定回調函數名稱
          success: function (data) {
                  //把success裏調用的函數改爲回調函數名。
                   storageSurvey(data);
          },
          error:function () {
            alert("error");
   }
}


function storageSurvey(data) {
    // 調用次數測試
    alert("test");

    //將後臺返回的數據先進行base64解碼,再轉換成json格式。
    function decode(rtnData){
                  var dstr = kvcommon.base64Decode(rtnData);
                  var rtnData = kvcommon.Ajax.Str2Json(dstr);
                  return rtnData;
              }
              var now_data = decode(data);
              var json = now_data[0];
              console.log(now_data);
              if(json.status == 0) {
                   var length = json.len;
                     modules = {};
                  //數據渲染
                   var modules = json.storage;
                  var max_count = json.max_count;
                  //在model_add()這個方法裏進行數據獲取和渲染
                   model_add(length,modules,max_count);

              }
}

再將ajax success中調用的函數名改爲回調函數名後,在此函數中加入一個alert(“test”),執行後發現test彈出了兩次。也就是說storageSurvey( )這個函數執行了兩次。再看下面這這段代碼:

//ajax方法
function total_tendency() {
      $.ajax({
          url: "/count/storage/data?callback=storageSurvey",
          dataType: "jsonp",  //指定服務器返回的數據類型爲jsonp
          type: "GET", 
          async:true,  
          jsonp: "callback", ///指定參數名稱,默認爲callback  
          jsonpCallback:"storageSurvey", //指定調用的回調函數名稱
          /* success: function (data) {
                  //把success裏調用的函數改爲回調函數名。
                   storageSurvey(data);
          },
          error:function () {
            alert("error");
  }*/
}

function storageSurvey(data) {
    // 調用次數測試
    alert("test");

    //將後臺返回的數據先進行base64解碼,再轉換成json格式。
    function decode(rtnData){
                  var dstr = kvcommon.base64Decode(rtnData);
                  var rtnData = kvcommon.Ajax.Str2Json(dstr);
                  return rtnData;
              }
              var now_data = decode(data);
              var json = now_data[0];
              console.log(now_data);
              if(json.status == 0) {
                   var length = json.len;
                     modules = {};
                  //數據渲染
                   var modules = json.storage;
                  var max_count = json.max_count;
                  //在model_add()這個方法裏進行數據獲取和渲染
                   model_add(length,modules,max_count); 
              }
}

將success和error屏蔽,執行代碼,有意思的是test還會彈出來,不過只彈出來了一次,意味着storageSurvey( )這個函數這次只執行了一次
看出jsop與ajax的區別了嗎?如果是ajax,你把在success中調用的函數屏蔽掉,它還會執行嗎?顯然不會!那麼在jsop中爲什麼會執行呢?原因就是這句話:
jsonpCallback:”storageSurvey”,
這句屬性的設置。它本意是設置請求url中callback=後面那個回調函數的名稱,但有意思的是,如果你在此ajax函數外的js中重寫了這麼一個函數,ajax就會直接調用此函數。jquery jsop的這個功能應該是基於原生的js調用jsop的方法,而原生js實現jsonp跨域也更能讓大家理解jsonp實現跨域的原理。看下面這段代碼:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
    function connect_data(data){
        alert("age:" + data.age + "name:" + data.name);
    }
</script>
<script type="text/javascript" src="jquery-1.8.3.min.js">
</script>
<script type="text/javascript" src="這裏寫服務器端調用此函數的文件路徑"></script>
</body>
</html>

然後只需在服務器端以connect_data( ) 命名的函數中返回json數據即可,如有需要,也可自行選擇加密方式,就如我在一開始的demo中用的就是base64decode。

從上面的這個demo中可以看出,jsonp的跨域原理就是利用了src可以避開同源策略這一特性,在原生js中需要手動包裹一層script,在src裏放請求路徑,在路徑裏的文件中傳輸jsop數據。而jquery jsonp則自動動態的給你包裹了一層script標籤和src屬性。

補充:

這是百度百科對同源策略的描述:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章