前言
由於瀏覽器存在同源策略的機制,所謂同源策略就是阻止從一個源(域名,包括同一個根域名下的不同二級域名)加載的文檔或者腳本獲取/或者設置
另一個源加載的文檔屬性.
但比較特別的是:由於同源策略是瀏覽器的限制,所以請求的響應和發送是可以進行的,只不過瀏覽器不支持罷了.
同源策略限制
瀏覽器的同源策略並不是對所有的請求都有限制的:
- 限制:XmlHttpRequest
- 不限制:img iframe script等等具有src屬性的標簽
利用src屬性標簽實現跨域請求
基本思路
利用script標簽,src導入目標域名的接口,在文檔數的head標簽中添加一行script標簽,得到內容后將scprit標簽刪除,返回的解析后的參數即為得到的數據.
利用script標簽實現跨域代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>Index</h1>
<input type="button" onclick="Ajax();" value="普通AJax"/>
<input type="button" onclick="Ajax2();" value="跨域普通AJax"/>
<input type="button" onclick="Ajax3();" value="跨域牛逼AJax"/>
<input type="button" onclick="Ajax4();" value="江西TV"/>
<script src="/static/jquery-2.1.4.min.js"></script>
<script>
// 原生ajax,測試無效
function Ajax(){
$.ajax({
url: '/get_data/',
type: 'POST',
data: {'k1': 'v1'},
success: function (arg) {
alert(arg);
}
})
}
// 使用ajax跨域請求,測試無效
function Ajax2(){
$.ajax({
url: 'http://wupeiqi.com:8001/api/',
type: 'GET',
data: {'k1': 'v1'},
success: function (arg) {
alert(arg);
}
})
}
// 利用script標簽,得到數據
function Ajax3(){
// script
// alert(api)
var tag = document.createElement('script');
tag.src = 'http://wupeiqi.com:8001/api/';
document.head.appendChild(tag);
document.head.removeChild(tag);
}
function fafafa(arg){
console.log(arg);
}
// 例子,獲取江西衛視的節目單
function Ajax4(){
// script
// alert(api)
var tag = document.createElement('script');
tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
document.head.appendChild(tag);
document.head.removeChild(tag);
}
function list(arg){
console.log(arg);
}
</script>
</body>
</html>
JSONP實現ajax跨域
以上的代碼其實也是jsonp的基本思路
基本的jsonp寫法
$.ajax({
url:..
type: 'GET',
dataType: 'jsonp',
//傳遞給請求處理程序或頁面的,用以獲得jsonp回調函數名的參數名(一般默認為:callback)
jsonp: 'callback',
//自定義的jsonp回調函數名稱,默認為jQuery自動生成的隨機函數名,也可以寫"?",jQuery會自動為你處理數據
jsonpCallback: 'list'
})
function list(arg){
}
解釋:
jsonp: callback #發送給請求處理程序的,被請求端通過request.GET.get("callback"),獲得jsonp回調函數的參數
jsonpCallback: 'list' #定義回調函數的名稱,然后后面通過list(...)來處理獲取數據
生產示例
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>
<input type="button" onclick="Jsonp1();" value='提交'/>
</p>
<p>
<input type="button" onclick="Jsonp2();" value='提交'/>
</p>
<script type="text/javascript" src="jquery-1.12.4.js"></script>
<script>
function Jsonp1(){
var tag = document.createElement('script');
tag.src = "http://c2.com:8000/test/";
document.head.appendChild(tag);
document.head.removeChild(tag);
}
function Jsonp2(){
$.ajax({
url: "http://c2.com:8000/test/",
type: 'GET',
dataType: 'JSONP',
success: function(data, statusText, xmlHttpRequest){
console.log(data);
}
})
}
</script>
</body>
</html>
###基於JSONP實現跨域Ajax - Demo
JSONP不能發送POST請求
究其根源,通過script標簽的src屬性進行跨域請求,<script src='http://www.jxntv.cn/data/jmd-jxtv2.html?callback=qwerqweqwe&_=1454376870403'>
最后全部都會轉換成GET請求,哪怕是你把type改為POST
.
別處copy的例子,供參考
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script type="text/javascript" src=jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
dataType: "jsonp",
jsonp: "callback",//傳遞給請求處理程序或頁面的,用以獲得jsonp回調函數名的參數名(一般默認為:callback)
jsonpCallback:"flightHandler",//自定義的jsonp回調函數名稱,默認為jQuery自動生成的隨機函數名,也可以寫"?",jQuery會自動為你處理數據
success: function(json){
alert('您查詢到航班信息:票價: ' + json.price + ' 元,余票: ' + json.tickets + ' 張。');
},
error: function(){
alert('fail');
}
});
});
</script>
</head>
<body>
</body>
</html>
其他ajax跨站請求方式
需要順帶提一句的是,跨站請求還有另一種方式:cors
,跨站資源共享,但此中方式對瀏覽器版本有要求,IE8以下的均不支持.
CORS與JSONP相比,無疑更為先進、方便和可靠。
1、 JSONP只能實現GET請求,而CORS支持所有類型的HTTP請求。
2、 使用CORS,開發者可以使用普通的XMLHttpRequest發起請求和獲得數據,比起JSONP有更好的錯誤處理。
3、 JSONP主要被老的瀏覽器支持,它們往往不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS(這部分會在后文瀏覽器支持部分介紹)。