首先,我們得了解一個概念,叫同源策略(same-origin policy).
比如,我們在寫自己公司的一個網站,然後我們需要從淘寶獲取商品信息,比如: https://www.taobao.com/goods,我們肯定拿不到,因爲存在這同源策略,一下是同源策略的定義.
不同域的客戶端腳本沒有授權的情況下不能讀寫對方的資源。
只有在同協議,同域名,同端口 下才能成爲同域。
比如,以上例子可以看出,只有最後一個跟http://ke.qq.com同域,也就是說可以直接訪問獲取數據。
有常用的3中繞開這個限制的方法
- CORS(cross domain resourse sharing)
- JSONP(json with padding)
- 藉助iframe跨域
下面着重來介紹一下JSONP.
首先,我們得了解script標籤是可以越過這個限制的,我們在寫Jquery的時候,就會用到谷歌的Jquery的cdn,比如一下代碼。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
只要我們引用過來,我們的網站裏就可以使用Jquery,是因爲script標籤不受同源策略的限制,因此我們也可以受這個啓發。
在JSONP,當我們給服務器發用script標籤發請求的時候我們傳特殊的參數來說明一下我們頁面的情況,這樣的話,服務器會客戶端可以接受的形式來返回。
比如,服務器期望接受一個叫callback來使JSONP可行,你的請求應該使這樣的。
http://www.example.net/sample.aspx?callback=mycallback
如果沒有JSONP,服務器應該這樣返回,比如:
{ foo:'bar' }
但有了JSONP,有了請求時候的一個參數 callback,服務器會把以不同的形式返回,比如:
mycallback({foo:'bar'});
可以看到這個返回會調用我們指定的方法,因此,在我們的頁面裏,我們可以定義一下函數:
mycallback = function(data){
alert(data.foo);
};
然後返送請求的時候,我們頁面寫的方法會被執行,跨域完成。
下面是用了JSONP的實際例子:
<!DOCTYPE html>
<html>
<body>
<p id="paragraphElement"></p>
<!-- The server returns a call to the callback function
(processData) that will handle the JSON data -->
<script>
function processData(myObj) {
console.log(myObj);
var para= document.getElementById("paragraphElement");
for(var i=0; i<myObj.resultCount; i++){
para.innerHTML= para.innerHTML + myObj.results[i].trackName
+ "<br>" ;
}
}
</script>
<!-- Calling the iTunes API to search for Jack Johnson's songs and return
the first five items -->
<script src="https://itunes.apple.com/search?term=jack+johnson&limit=5
&callback=processData"></script>
</body>
</html>
在實際開發的時候不能自己填寫上去,必須得自動化,下面是簡單的自動化構造JSONP的代碼.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
window.onload=createScriptDynamically();
function createScriptDynamically(){
const url="https://itunes.apple.com/search?term=taylor+swift&limit=5&callback=processData";
let scriptElement=document.createElement('script');
scriptElement.setAttribute('src',url);
scriptElement.setAttribute('id','jsonP');
let head=document.getElementsByTagName('head')[0];
head.appendChild(scriptElement);
console.log(head);
}
function processData(data){
console.log(data);
}
</script>
</body>
</html>
更多請參考