首先,我们得了解一个概念,叫同源策略(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>
更多请参考