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

來源:互聯網
上載者:User

前言

  第一次聽說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?callback=jsonpcallback"; 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方法中。

<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> <?php $jsondata = '{ "name": "hanzichi", "age": 10 }'; echo $_GET['callback'].'('.$jsondata.')';?> 

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

// 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指令碼。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.