JSNOP是一個非官方的協議,它允許在服務器端集成script tags返回至客戶端,通過JavaScript callback的形式實現跨域訪問。
由于同源策略的限制,XMLHttpRequest只允許請求當前源(域名、協議、端口)的資源,為了實現跨域請求,可以通過script標簽實現跨域請求,然后在服務端輸出json數據并執行回調函數,從而解決了跨域的數據請求。
使用jsonp:
a.第一種方法
<meta??? content="text/html;chartset=utf-8"???? http-equiv="Content-Type">
<script>
function jsonpCallback(result) {
//alert(result);
for(var?i?in?result)?{
alert(i+":"+result[i]);//循環輸出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>
b.第二種方法
<meta? ? content="text/html;chartset=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]);//循環輸出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數據
$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)";
//動態執行回調函數
$callback=$_GET['callback'];
echo??? $callback."($result)";
如果將上述JS客戶端代碼用jQuery的方法來實現,也非常簡單。
$.getJSON
$.ajax
$.get
客戶端JS代碼在jQuery中的實現方式1:
<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]);//循環輸出a:1,b:2,etc.
}
});
</script>
客戶端JS代碼在jQuery中的實現方式2:
<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(variinresult)?{
alert(i+":"+result[i]);//循環輸出a:1,b:2,etc.
}
},
timeout:3000
});
</script>
客戶端JS代碼在jQuery中的實現方式3:
<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(variinjson) alert(i+":"+json[i]); },'jsonp');
</script>
其中 jsonCallback 是客戶端注冊的,獲取跨域服務器上的json數據后,回調的函數。
http://crossdomain.com/services.php?callback=jsonpCallback
這個 url 是跨域服務器取 json 數據的接口,參數為回調函數的名字,返回的格式為Js代碼:
jsonpCallback({msg:'this?is?json?data'})
Jsonp原理:
首先在客戶端注冊一個callback, 然后把callback的名字傳給服務器。
此時,服務器先生成 json 數據。
然后以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數 jsonp.
最后將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
客戶端瀏覽器,解析script標簽,并執行返回的 javascript 文檔,此時數據作為參數,傳入到了客戶端預先定義好的 callback 函數里.(動態執行回調函數)
使用JSON的優點在于:
比XML輕了很多,沒有那么多冗余的東西。
JSON也是具有很好的可讀性的,但是通常返回的都是壓縮過后的。不像XML這樣的瀏覽器可以直接顯示,瀏覽器對于JSON的格式化的顯示就需要借助一些插件了。
在JavaScript中處理JSON很簡單。
其他語言例如PHP對于JSON的支持也不錯。
JSON也有一些劣勢:
JSON在服務端語言的支持不像XML那么廣泛,不過JSON.org上提供很多語言的庫。
如果你使用eval()來解析的話,會容易出現安全問題。
盡管如此,JSON的優點還是很明顯的。他是Ajax數據交互的很理想的數據格式。
JSONP 是構建 mashup
的強大技術,但不幸的是,它并不是所有跨域通信需求的萬靈藥。它有一些缺陷,在提交開發資源之前必須認真考慮它們。
第一,也是最重要的一點,沒有關于
JSONP 調用的錯誤處理。如果動態腳本插入有效,就執行調用;如果無效,就靜默失敗。失敗是沒有任何提示的。例如,不能從服務器捕捉到 404
錯誤,也不能取消或重新開始請求。不過,等待一段時間還沒有響應的話,就不用理它了。(未來的 jQuery 版本可能有終止 JSONP
請求的特性)。
JSONP 的另一個主要缺陷是被不信任的服務使用時會很危險。因為 JSONP 服務返回打包在函數調用中的 JSON
響應,而函數調用是由瀏覽器執行的,這使宿主 Web 應用程序更容易受到各類攻擊。如果打算使用 JSONP 服務,了解它能造成的威脅非常重要。