Jsonp 關鍵字詳解及json和jsonp的區別,ajax和jsonp的區別


為什么要用jsonp?

  相信大家對跨域一定不陌生,對同源策略也同樣熟悉。什么,你沒聽過?沒關系,既然是深入淺出,那就從頭說起。

  假如我寫了個index頁面,頁面里有個請求,請求的是一個json數據(不知道json數據的猛戳JSON簡介以及用法匯總),簡單思考寫下如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script type= "text/javascript" >
  $.ajax({
  dataType: "json" ,
  success: function (data) {
   console.log(data);
  }
  })
</script>
{
  "name" : "hanzichi" ,
  "age" : 10
}

  樓主把兩個文件都放在wamp下的www文件夾下,ajax請求沒有跨域,完美得到結果:

  但是如果我的json文件和index文件不在一個域下,即跨域(不懂跨域的可參考JavaScript 的同源策略)了呢?

  試着在wamp下新開個apache端口(不知道怎么開的可參考WampServer下使用多端口訪問),將json文件放到該服務端口的文件夾下(樓主設置的端口號為8080,默認的是80端口),試着發送請求: 

?
1
2
3
4
5
6
7
8
9
10
<script type= "text/javascript" >
  $.ajax({
  dataType: "json" ,
  success: function (data) {
   console.log(data);
  }
  })
</script>

  很顯然,提示跨域了!怎么搞?這時jsonp就要出馬了!

神奇的script標簽

  與jsonp息息相關的是script標簽,而xhr或者說傳統意義上的ajax與之沒有半毛錢關系!

  接着看上面的index.html代碼,我們看到頁面引用了百度cdn的jquery路徑,對於這樣的方式我們似乎已經習以為常,但是仔細一想,script標簽可是完完全全的跨域的啊...沒錯,jsonp的實現核心就是利用script標簽的跨域能力!於是我們靈機一動,似乎可以這么搞,動態生成一個script標簽,把json的url賦值給script的src屬性,然后再把這個script標簽插入dom里...

?
1
2
3
4
5
6
7
8
<body>
  <script type= "text/javascript" >
  var s = document.createElement( 'script' );
  document.body.appendChild(s);
  </script>
</body>

  我們創建了一個script標簽,而標簽內包裹的內容正是需要的json數據,但是報錯如下:

 

  原因是因為json數據並不是合法的js語句,把上面的json數據放在一個回調函數中是最簡單的方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<body>
  <script type= "text/javascript" >
  function jsonpcallback(json) {
   console.log(json);
  }
  var s = document.createElement( 'script' );
  document.body.appendChild(s);
  </script>
</body>
jsonpcallback({
  "name" : "hanzichi" ,
  "age" : 10
});

  當然,這時的a.json文件並不一定要這樣命名,改成a.js也不會有一點問題。

  而如果是與服務端交互也是一樣的道理,比如和php:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body>
  <script type= "text/javascript" >
  function jsonpcallback(json) {
   console.log(json);
  }
  var s = document.createElement( 'script' );
  document.body.appendChild(s);
  </script>
</body>
<?php
  $jsondata = '{
  "name": "hanzichi",
  "age": 10
  }' ;
  echo $_GET[ 'callback' ]. '(' .$jsondata. ')' ;
?>

  需要注意的是,jsonp提供的url(即動態生成的script標簽的src),無論看上去是什么形式,最終生成返回的都是一段js代碼。

JQuery對jsonp的封裝

  為了便於開發,jq對jsonp也進行了封裝,封裝在了ajax方法中。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script type= "text/javascript" >
  $.ajax({
  dataType: 'jsonp' ,
  jsonpCallback: 'CallBack' ,
  success: function (data) {
   console.log(data);
  }
  });
</script>
CallBack({
  "name" : "hanzichi" ,
  "age" : 10
});

  以上代碼是針對請求文件中寫死了callback函數名的情況。因為請求的是json文件,json不是服務器端的動態語言不能進行解析,如果是php或者其他的服務器端語言,則不用寫死函數名,比如下面這樣:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script type= "text/javascript" >
  $.ajax({
  dataType: 'jsonp' ,
  success: function (data) {
   console.log(data);
  }
  });
</script>
<?php
  $jsondata = '{
  "name": "hanzichi",
  "age": 10
  }' ;
  echo $_GET[ 'callback' ]. '(' .$jsondata. ')' ;
?>

   當然類似的封裝好的方法還有幾種:

?
1
2
3
4
5
6
7
8
// 1
$.getJSON( "http://localhost:8080/test.php?callback=?" , function (data) {
  console.log(data);
});
// 2
$.get( 'http://localhost:8080/test.php' , function (data) {
  console.log(data);
}, 'jsonp' );

  需要注意的是getJSON方法的請求地址url需要帶上callback=?,因為jq對該方法進行封裝的時候並沒有默認回調函數變量名為callback,於是php中$_GET['callback']就找不到變量值了。

  而一般的jq方法url 中不用指定 callback 參數。對於 jQuery 中的 jsonp 來說,callback 參數是自動添加的。默認情況下,jQuery 生成的 jsonp 請求中 callback 參數是形如 callback=jQuery200023559735575690866_1434954892929 這種根據看似隨機的名字,對應的就是 success 那個處理函數,所以一般不用特意處理。二如果要寫死callback名的話,可以參照上文。

 

總結

  由於同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協議、端口)的資源,為了實現跨域請求,可以通過script標簽實現跨域請求,然后在服務端輸出JSON數據並執行回調函數,從而解決了跨域的數據請求,這就是jsonp的核心。

  jsonp原理:

 1.首先在客戶端注冊一個callback, 然后把callback的名字傳給服務器。
 2.服務器先生成 json 數據。 然后以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數 jsonp. 最后將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
 3.客戶端瀏覽器,解析script標簽,並執行返回的 javascript 文檔,此時數據作為參數,傳入到了客戶端預先定義好的 callback 函數里.(動態執行回調函數)

 json和jsonp的區別,ajax和jsonp的區別

 json和jsonp雖然只有一個字母的區別,但是它們之間扯不上關系。

json是一種輕量級的數據交換格式。

jsonp是一種跨域數據交互協議。

json的優點:(1)基於純文本傳遞極其簡單,(2)輕量級數據格式適合互聯網傳遞,(3)容易編寫和解析。

ajax和jsonp的區別:

相同點:都是請求一個url

不同點:ajax的核心是通過xmlHttpRequest獲取內容

    jsonp的核心則是動態添加<script>標簽來調用服務器 提供的js腳本。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM