AJAX跨域請求之JSONP獲取JSON數(shù)據(jù)
Asynchronous JavaScript and XML (Ajax ) 是驅(qū)動新一代 Web 站點(流行術(shù)語為 Web 2.0 站點)的關(guān)鍵技術(shù)。Ajax 允許在不干擾 Web 應用程序的顯示和行為的情況下在后臺進行數(shù)據(jù)檢索。使用 XMLHttpRequest 函數(shù)獲取數(shù)據(jù),它是一種 API,允許客戶端 JavaScript 通過 HTTP 連接到遠程服務器。Ajax 也是許多 mashup 的驅(qū)動力,它可將來自多個地方的內(nèi)容集成為單一 Web 應用程序。
不過,由于受到瀏覽器的限制,該方法不允許跨域通信。如果嘗試從不同的域請求數(shù)據(jù),會出現(xiàn)安全錯誤。如果能控制數(shù) 據(jù)駐留的遠程服務器并且每個請求都前往同一域,就可以避免這些安全錯誤。但是,如果僅停留在自己的服務器上,Web 應用程序還有什么用處呢?如果需要從多個第三方服務器收集數(shù)據(jù)時,又該怎么辦?
理解同源策略限制
同源策略阻止從一個域上加載的腳本獲取或操作另一個域上的文檔屬性。也就是說,受到請求的 URL 的域必須與當前 Web 頁面的域相同。這意味著瀏覽器隔離來自不同源的內(nèi)容,以防止它們之間的操作。這個瀏覽器策略很舊,從 Netscape Navigator 2.0 版本開始就存在。
克服該限制的一個相對簡單的方法是讓 Web 頁面向它源自的 Web 服務器請求數(shù)據(jù),并且讓 Web 服務器像代理一樣將請求轉(zhuǎn)發(fā)給真正的第三方服務器。盡管該技術(shù)獲得了普遍使用,但它是不可伸縮的。另一種方式是使用框架要素在當前 Web 頁面中創(chuàng)建新區(qū)域,并且使用 GET 請求獲取任何第三方資源。不過,獲取資源后,框架中的內(nèi)容會受到同源策略的限制。
克服該限制更理想方法是在 Web 頁面中插入動態(tài)腳本元素,該頁面源指向其他域中的服務 URL 并且在自身腳本中獲取數(shù)據(jù)。腳本加載時它開始執(zhí)行。該方法是可行的,因為同源策略不阻止動態(tài)腳本插入,并且將腳本看作是從提供 Web 頁面的域上加載的。但如果該腳本嘗試從另一個域上加載文檔,就不會成功。幸運的是,通過添加 JavaScript Object Notation (JSON) 可以改進該技術(shù)。
1、什么是JSONP?
要了解JSONP,不得不提一下JSON,那么什么是JSON ?
JSON is a subset of the object literal notation of JavaScript. Since JSON is a subset of JavaScript, it can be used in the language with no muss or fuss.
JSONP(JSON with Padding)是一個非官方的協(xié)議,它允許在服務器端集成Script tags返回至客戶端,通過javascript callback的形式實現(xiàn)跨域訪問(這僅僅是JSONP簡單的實現(xiàn)形式)。
2、JSONP有什么用?
由于同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協(xié)議、端口)的資源,為了實現(xiàn)跨域請求,可以通過script標簽實現(xiàn)跨域請求,然后在服務端輸出JSON數(shù)據(jù)并執(zhí)行回調(diào)函數(shù),從而解決了跨域的數(shù)據(jù)請求。
3、如何使用JSONP?
下邊這一DEMO實際上是JSONP的簡單表現(xiàn)形式,在客戶端聲明回調(diào)函數(shù)之后,客戶端通過script標簽向服務器跨域請求數(shù)據(jù),然后服務端返回相應的數(shù)據(jù)并動態(tài)執(zhí)行回調(diào)函數(shù)。
HTML代碼 (任一 ):
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <script type="text/javascript"> function jsonpCallback(result) { //alert(result); for(var i in result) { alert(i+":"+result[i]);//循環(huán)輸出a:1,b:2,etc. } } var JSONP=document.createElement("script"); JSONP.type="text/javascript"; JSONP.src="http://crossdomain.com/services.php?callback=jsonpCallback"; document.getElementsByTagName("head")[0].appendChild(JSONP); </script>
或者
Html代碼
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <script type="text/javascript"> function jsonpCallback(result) { alert(result.a); alert(result.b); alert(result.c); for(var i in result) { alert(i+":"+result[i]);//循環(huán)輸出a:1,b:2,etc. } } </script> <script type="text/javascript" src="http://crossdomain.com/services.php?callback=jsonpCallback"></script>
JavaScript的鏈接,必須在function的下面。
服務端PHP代碼 (services.php):
<?php //服務端返回JSON數(shù)據(jù) $arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5); $result=json_encode($arr); //echo $_GET['callback'].'("Hello,World!")'; //echo $_GET['callback']."($result)"; //動態(tài)執(zhí)行回調(diào)函數(shù) $callback=$_GET['callback']; echo $callback."($result)";
如果將上述JS客戶端代碼用jQuery的方法來實現(xiàn),也非常簡單。
$.getJSON
$.ajax
$.get
客戶端JS代碼在jQuery中的實現(xiàn)方式1:
Js代碼
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $.getJSON("http://crossdomain.com/services.php?callback=?", function(result) { for(var i in result) { alert(i+":"+result[i]);//循環(huán)輸出a:1,b:2,etc. } }); </script>
客戶端JS代碼在jQuery中的實現(xiàn)方式2:
Js代碼
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $.ajax({ url:"http://crossdomain.com/services.php", dataType:'jsonp', data:'', jsonp:'callback', success:function(result) { for(var i in result) { alert(i+":"+result[i]);//循環(huán)輸出a:1,b:2,etc. } }, timeout:3000 }); </script>
客戶端JS代碼在jQuery中的實現(xiàn)方式3:
Js代碼
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $.get('http://crossdomain.com/services.php?callback=?', {name: encodeURIComponent('tester')}, function (json) { for(var i in json) alert(i+":"+json[i]); }, 'jsonp'); </script>
其中 jsonCallback 是客戶端注冊的,獲取 跨域服務器 上的json數(shù)據(jù) 后,回調(diào)的函數(shù)。
http://crossdomain.com/services.php?callback=jsonpCallback
這個 url 是跨域服務 器取 json 數(shù)據(jù)的接口,參數(shù)為回調(diào)函數(shù)的名字,返回的格式為
Js代碼
jsonpCallback({msg:'this is json data'})
Jsonp原理:
首先在客戶端注冊一個callback, 然后把callback的名字傳給服務器。
此時,服務器先生成 json 數(shù)據(jù)。
然后以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數(shù) jsonp.
最后將 json 數(shù)據(jù)直接以入?yún)⒌姆绞?,放置?function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
客戶端瀏覽器,解析script標簽,并執(zhí)行返回的 javascript 文檔,此時數(shù)據(jù)作為參數(shù),傳入到了客戶端預先定義好的 callback 函數(shù)里.(動態(tài)執(zhí)行回調(diào)函數(shù))
使用JSON的優(yōu)點在于:
比XML輕了很多,沒有那么多冗余的東西。
JSON也是具有很好的可讀性的,但是通常返回的都是壓縮過后的。不像XML這樣的瀏覽器可以直接顯示,瀏覽器對于JSON的格式化的顯示就需要借助一些插件了。
在JavaScript中處理JSON很簡單。
其他語言例如PHP對于JSON的支持也不錯。
JSON也有一些劣勢:
JSON在服務端語言的支持不像XML那么廣泛,不過JSON.org上提供很多語言的庫。
如果你使用eval()來解析的話,會容易出現(xiàn)安全問題。
盡管如此,JSON的優(yōu)點還是很明顯的。他是Ajax數(shù)據(jù)交互的很理想的數(shù)據(jù)格式。
主要提示:
JSONP 是構(gòu)建 mashup 的強大技術(shù),但不幸的是,它并不是所有跨域通信需求的萬靈藥。它有一些缺陷,在提交開發(fā)資源之前必須認真考慮它們。
第一,也是最重要的一點,沒有關(guān)于 JSONP 調(diào)用的錯誤處理。如果動態(tài)腳本插入有效,就執(zhí)行調(diào)用;如果無效,就靜默失敗。失敗是沒有任何提示的。例如,不能從服務器捕捉到 404 錯誤,也不能取消或重新開始請求。不過,等待一段時間還沒有響應的話,就不用理它了。(未來的 jQuery 版本可能有終止 JSONP 請求的特性)。
JSONP 的另一個主要缺陷是被不信任的服務使用時會很危險。因為 JSONP 服務返回打包在函數(shù)調(diào)用中的 JSON 響應,而函數(shù)調(diào)用是由瀏覽器執(zhí)行的,這使宿主 Web 應用程序更容易受到各類攻擊。如果打算使用 JSONP 服務,了解它能造成的威脅非常重要。
相關(guān)文章
前端ajax請求+后端java實現(xiàn)的下載zip壓縮包功能示例
這篇文章主要介紹了前端ajax請求+后端java實現(xiàn)的下載zip壓縮包功能,結(jié)合實例形式分析了ajax請求交互與后端圖片zip格式壓縮并下載功能相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2023-05-05Ajax中post方法直接返回以0開頭數(shù)字出錯問題分析
這篇文章主要介紹了Ajax中post方法直接返回以0開頭數(shù)字出錯問題分析,需要的朋友可以參考下2017-03-03使用AjaxFileUpload.js實現(xiàn)異步文件上傳示例
AjaxFilleUpload.js可以使得我們不用去管理Iframe的一系列操作,也不用影響我們的頁面結(jié)構(gòu),實現(xiàn)異步的文件提交2014-05-05Ajax+Servlet實現(xiàn)無刷新下拉聯(lián)動效果
這篇文章主要為大家詳細介紹了Ajax+Servlet實現(xiàn)無刷新下拉聯(lián)動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11使用$.getJSON實現(xiàn)跨域ajax請求示例代碼
getJSON調(diào)用并獲取遠程的JSON字符串,將其轉(zhuǎn)換為JSON對象,如果成功,則執(zhí)行回調(diào)函數(shù),下面有個不錯的示例,需要的朋友可以參考下2013-11-11ajax異步回調(diào)函數(shù)中給外部變量賦值的問題探討
ajax異步回調(diào)函數(shù)中給外部變量賦值的問題在本文將為大家詳細探討下,感興趣的朋友可以參考下2013-09-09ajax+asp無限級分類樹型結(jié)構(gòu)的代碼
ajax+asp無限級分類樹型結(jié)構(gòu)的代碼...2007-10-10分頁技術(shù)原理與實現(xiàn)之無刷新的Ajax分頁技術(shù)(三)
這篇文章主要介紹了分頁技術(shù)原理與實現(xiàn)的第三篇:無刷新的Ajax分頁技術(shù),感興趣的小伙伴們可以參考一下2016-06-06