在一個head標(biāo)簽中我們可以這么寫
<script>
var callback = function(data){
console.log(data);
}
callback({name:'王柯智',age:'18'})
// 在控制臺打印出 {name:'王柯智',age:'18'}
</script>
我們定義了一個函數(shù)祈噪,然后我們又調(diào)用了這個函數(shù)糙俗,接下來我們把調(diào)用函數(shù)這句話(callback({name:'王柯智',age:'18'}))
放在同級目錄下的另外一個JS文件叫做jsonp.js文件中,接下來我們的head標(biāo)簽就可以這么寫
<script>
var callback = function(data){
console.log(data);
}
</script>
<script src='./jsop.js'>
</script>
以上代碼跟第一次我們寫的代碼效果一模一樣。但是我們是從引入外部的JS來調(diào)用我們自己定義的函數(shù)酝锅。
如果把這個外部js放在服務(wù)器上的話,我們的script標(biāo)簽可以會變成這種形式:
<script src='http://xxx.com/jsonp.js'>
</script>
然后我們在服務(wù)器的jsonp.js文件里可以把服務(wù)器的數(shù)據(jù)拿到JS當(dāng)中奢方,也就是說這里的JS是這么寫的
callback({key1:'value',key2:'value2'})
由于我們可能會多次調(diào)用callback函數(shù)搔扁,為了把每次調(diào)用的函數(shù)和函數(shù)調(diào)用后得到的結(jié)果對應(yīng)起來,通常我們會為這個函數(shù)取一個隨機的名字袱巨,代碼實現(xiàn)如下:
var num = Math.floor(Math.random() * 100000) // num是一個1到10萬隨機數(shù)
window.callbackName = 'callback_' + num; //給windou添加一個全局屬性callbackName
window[callbackName] = function(data){
console.log(data);
}
此時我們定義便有了一個callback便有了一個隨機的名字阁谆,但是問題來了,由于我們定義的函數(shù)名是隨機的愉老,我們自己都不知道如何調(diào)用场绿,我們怎么使服務(wù)器上的那個函數(shù)名變成我們的函數(shù)名呢?
JSONP給出了一個方法嫉入,即在你需要加載的js文件后面加上'焰盗?callback="你的函數(shù)名"',所以我們的script標(biāo)簽便需要這樣寫:
<script src='http://xxx.com/jsopn.js?callback='+callbackName>
這樣我們就能把服務(wù)器上的函數(shù)名callback改成我們這里定義的函數(shù)名了咒林。
可是還有個問題熬拒,我們使用了2個script標(biāo)簽,一般來說垫竞,第二個script我們需要他動態(tài)加載澎粟,所以我們只需要使用一個scirpt標(biāo)簽:
<script>
var num = Math.floor(Math.random() * 100000) // num是一個1到10萬隨機數(shù)
window.callbackName = 'callback_' + num; //給windou添加一個全局屬性callbackName
window[callbackName] = function(data){
console.log(data);
}
//定義我們自己的函數(shù),并給他賦予一個隨機的名字
var sc = document.create('script')
sc.src = 'http://xxx.com/jsopn.js?callback=' + callbackName;
sc.id = 'script_' + callbackName;
document.body.appendChild(sc);
// script標(biāo)簽只有添加到文檔當(dāng)中才會去請求資源欢瞪。
document.getElementById(sc.id).remove();
//當(dāng)函數(shù)被調(diào)用以后得到了服務(wù)器端的數(shù)據(jù)便把script標(biāo)簽從文檔中移除.
</script>
以上便是JSONP的用法活烙。
當(dāng)然,我們可以給callback不同的功能遣鼓,比如上述代碼中我們callback的功能是打印出data啸盏,你也可以再寫一個callback,比如里面的代碼是console.log('xxx')也是可以的骑祟,但是這樣的話你可能會重寫一次上面的代碼回懦,會顯得很麻煩,所以我們把JSONP封裝一下次企,變成下面這個樣子:
function jsonp(url,fn){
var num = Math.floor(Math.random() * 100000);
var callbackName = 'callback_' + num;
window[callbackName] = fn;
var sc = document.createElement('script');
sc.src = url + '?callback=' + callbackName;
sc.id = 'script_' + num;
document.body.appendChild(sc);
document.getElementById(sc.id).remove()
}
這樣怯晕,當(dāng)我們想用jsonp的方式獲取數(shù)據(jù)并且對數(shù)據(jù)進行處理的話就可以直接運行
jsonp('http://www.xxx.com/jsop.js',function(data){
console.log(data);
})
當(dāng)然,我們也推薦使用JQuery的封裝好的JSONP語法:
$.ajax({
url:'http://www.xxx.com/jsonp.js',
datatype:'jsonp',
success:function(data){
console.log(data);
}
}
)
不過需要注意的是缸棵,雖然JQ這里寫的是$.ajax贫贝,但是JSONP并不是Ajax,這樣寫只是為了方便而把Ajax和JSONP的功能封裝在了一起,你在瀏覽器下打開開發(fā)者工具可以看到j(luò)sop的請求類型不是xhr稚晚。