AJAX經(jīng)常用來異步請求數(shù)據(jù),并且局部更新頁面。但是AJAX有一個很大的問題,它只能請求相同域名下的內(nèi)容。如果是請求不同域名下的內(nèi)容和數(shù)據(jù),不管是什么內(nèi)容,都不會成功。這就需要JSONP來進行跨域請求數(shù)據(jù)。
一、 前提
在JS和HTML中,其實跨域是很常見的。img標簽、script標簽都可以直接跨域來獲取其它網(wǎng)站的內(nèi)容。這就表示,我們通過使用script來跨域請求是完全可行的。而且因為JSON的存在,提供了一種非常適合數(shù)據(jù)交換的語法格式,而JSON恰好又被原生JS支持。
二、 理解JSONP的三個demo
1. 使用script跨域
本地有一個index.html的文件,內(nèi)容如下:
<body>
<script src="http://127.0.0.1:8080/test.js"></script>
</body>
本地域名為:127.0.0.1:8081,script標簽是在跨域請求
test.js的內(nèi)容:
alert('我是遠程文件')
當在http協(xié)議打開index.html文件時,彈出“我是遠程文件”,表示跨域成功。
2. 稍微變通一下
遠程的test.js改為:
handler({"name":"limingru"})
本地index.html改成:
<body>
<script>
function handler(data){
document.write(data.name)
}
</script>
<script src="http://127.0.0.1:8080/test.js"></script> //這里就相當于在script標簽里寫了handler({"name":"limingru"}),調(diào)用了上面準備好的函數(shù)。
</body>
這樣,在頁面里就寫入了limingru了。
3.理解JSONP
寫到這里,大致就能理解JSONP的基本邏輯了,JSONP就是通過客戶端通過script腳本來跨域調(diào)用其它服務(wù)器上動態(tài)生成的JS格式的文件,而用于交互的數(shù)據(jù)的格式則是JSON。調(diào)用成功以后,客戶端就跨域獲得了服務(wù)器的數(shù)據(jù),這樣就可以通過JS來展示這些數(shù)據(jù)了。
到這里還有一個問題。就是拿數(shù)據(jù)和給數(shù)據(jù)的雙方要共同約定一種格式,JSONP是通過函數(shù)參數(shù)傳遞的方式來給數(shù)據(jù)的,那給數(shù)據(jù)的一方如何知道拿數(shù)據(jù)的一方的函數(shù)呢?用查詢參數(shù)來約定,比如callback,它們的值就是共同的函數(shù)名稱和其它需要的信息。
來看第三個demo:
本地index.html內(nèi)容為:
<body>
<div></div>
<div></div>
<div></div>
<script>
function handler(data){
var divs = document.querySelectorAll('div')
divs[0].textContent = data.name
divs[1].textContent = data.gender
divs[2].textContent = data.age
}
var url = 'http://127.0.0.1:8080/test.js?callback=handler'
var script = document.createElement('script')
script.setAttribute('src',url)
document.querySelector('body').appendChild(script)
</script>
</body>
index.html文件動態(tài)生成script標簽,并且加上url,在url還給了一個查詢參數(shù)callback=handler,它告訴服務(wù)器返回一個handler來傳遞服務(wù)器的JSON數(shù)據(jù)。
服務(wù)器會根據(jù)查詢參數(shù)生成相應(yīng)的test.js文件:
handler({
"name":"limingru",
"gender": "male",
"age": 18
})
并且將相應(yīng)的數(shù)據(jù)傳過去。這樣,在本地頁面就能展示跨域獲得的數(shù)據(jù)了。
三、用jQuery通過JSONP跨域獲取數(shù)據(jù)
$.ajax({
type: "get",
async: false,
url: "http://xxx.aspx",
dataType: "jsonp",
jsonp: "callback",//傳遞給請求處理程序或頁面的,用以獲得jsonp回調(diào)函數(shù)名的參數(shù)名(一般默認為:callback)
jsonpCallback:"flightHandler",//自定義的jsonp回調(diào)函數(shù)名稱,默認為jQuery自動生成的隨機函數(shù)名,也可以寫"?",jQuery會自動為你處理數(shù)據(jù)
success: function(json){
alert('您查詢到航班信息:票價: ' + json.price + ' 元,余票: ' + json.tickets + ' 張。')
},
error: function(){
alert('失敗');
}
})
jQuery將JSONP封裝到了AJAX里,但實際上它們完全不一樣。要記住這一點。