ホームページ >ウェブフロントエンド >jsチュートリアル >Jsonpキーワードの詳細説明とjsonとjsonpの違い、ajaxとjsonp_javascriptスキルの違い

Jsonpキーワードの詳細説明とjsonとjsonpの違い、ajaxとjsonp_javascriptスキルの違い

WBOY
WBOYオリジナル
2016-05-16 15:22:411417ブラウズ

前言

  第一次聽到jsonp,其實早在2年之前。當時在做一個活動頁面的抽獎模組,要從服務端get一個機率,當時什麼都不懂,同事說用ajax,我就用ajax,同事說dataType改成jsonp,我就改成jsonp。於是乎活動頁面做完了,以後也沒有碰到過jsonp,在這段期間我一直以為jsonp跟ajax息息相關,是xhr的一種特殊的跨域形式...直到一個月前的一次面試,問到jsonp我被虐成狗,才決定看下jsonp,好吧,原來jsonp也不是很難。

為什麼要用jsonp?

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

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

<script src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
 $.ajax({
 url: 'http://localhost/a.json',
 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埠),試著發送請求: 

<script src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
 $.ajax({
 url: 'http://localhost:8080/a.json',
 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裡...

<body>
 <script src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
 <script type="text/javascript">
 var s = document.createElement('script');
 s.src = 'http://localhost:8080/a.json';
 document.body.appendChild(s);
 </script>
</body> 

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

 

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

<body>
 <script src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
 <script type="text/javascript">
 function jsonpcallback(json) {
  console.log(json);
 }
 var s = document.createElement('script');
 s.src = 'http://localhost:8080/a.json';
 document.body.appendChild(s);
 </script>
</body> 
jsonpcallback({
 "name": "hanzichi",
 "age": 10
}); 

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

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

<body>
 <script src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
 <script type="text/javascript">
 function jsonpcallback(json) {
  console.log(json);
 }
 var s = document.createElement('script');
 s.src="http://localhost:8080/test.php&#63;callback=jsonpcallback";
 document.body.appendChild(s);
 </script>
</body> 
<&#63;php
 $jsondata = '{
 "name": "hanzichi",
 "age": 10
 }';
 echo $_GET['callback'].'('.$jsondata.')';
&#63;> 

  要注意的是,jsonp提供的url(即動態產生的script標籤的src),無論看上去是什麼形式,最後產生回傳的都是一段js程式碼。

JQuery對jsonp的封裝

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

<script src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
 $.ajax({
 url: 'http://localhost:8080/a.json',
 dataType: 'jsonp',
 jsonpCallback: 'CallBack',
 success: function (data) {
  console.log(data);
 }
 });
</script> 
CallBack({
 "name": "hanzichi",
 "age": 10
}); 

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

<script src='http://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
 $.ajax({
 url: 'http://localhost:8080/test.php',
 dataType: 'jsonp',
 success: function (data) {
  console.log(data);
 }
 });
</script> 
<&#63;php
 $jsondata = '{
 "name": "hanzichi",
 "age": 10
 }';
 echo $_GET['callback'].'('.$jsondata.')';
&#63;> 

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

// 1
$.getJSON("http://localhost:8080/test.php&#63;callback=&#63;", 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 にコールバック パラメーターを指定する必要はありません。 jQuery の jsonp の場合、コールバック パラメーターは自動的に追加されます。デフォルトでは、jQuery によって生成される jsonp リクエストのコールバック パラメーターは callback=jQuery200023559735575690866_1434954892929 という形式になっており、この一見ランダムな名前は成功処理関数に対応するため、通常は特別に処理する必要はありません。 2. コールバック名を書き留めたい場合は、上記を参照してください。

概要

同一オリジン ポリシーの制限により、XmlHttpRequest では現在のソース (ドメイン名、プロトコル、ポート) からのリソースのリクエストのみが許可されます。クロスドメイン リクエストを実装するには、次のようにします。 script タグを指定し、サーバー上に JSON データを出力して実行します。コールバック関数は、jsonp の核となるクロスドメイン データ リクエストを解決します。

jsonp 原則:

1. まずクライアントでコールバックを登録し、次にそのコールバック名をサーバーに渡します。
2. サーバーはまず json データを生成します。 次に、JavaScript 構文を使用して関数を生成します。関数名は渡されたパラメーター jsonp です。最後に、json データがパラメーターとして関数に直接配置され、js 構文ドキュメントが生成されてクライアントに返されます。
3. クライアントのブラウザは script タグを解析し、返された JavaScript ドキュメントを実行します。このとき、データはクライアントによって事前に定義されたコールバック関数にパラメータとして渡されます (コールバック関数の動的実行)。

json と jsonp の違い、ajax と jsonp の違い

json と jsonp の間には 1 文字の違いがありますが、相互に関連はありません。


json は軽量のデータ交換フォーマットです。


jsonp は、クロスドメイン データ交換プロトコルです。


json の利点: (1) プレーンテキストに基づいて送信するのが非常に簡単、(2) 軽量なデータ形式はインターネット送信に適しています、(3) 記述と解析が簡単です。


ajax と jsonp の違い:


同じこと: どちらも URL をリクエストします


違い: ajax の核心は、xmlHttpRequest を通じてコン​​テンツを取得することです


jsonp の核心は、サーバーが提供する js スクリプトを呼び出すための 3f1c4e4b6b16bbbd69b2ee476dc4f83a タグを動的に追加することです。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。