借助script進(jìn)行Http跨域請(qǐng)求:JSONP實(shí)現(xiàn)原理及代碼
更新時(shí)間:2013年03月19日 14:51:09 作者:
script元素的src屬性能設(shè)置URL并發(fā)起HTTP GET請(qǐng)求實(shí)現(xiàn)腳本操作HTTP可以跨域通信而不受限與同源策略,接下來(lái)為大家詳細(xì)介紹下Http跨域請(qǐng)求實(shí)現(xiàn),感興趣的你可以參考下哈
<script>元素的src屬性能設(shè)置URL并發(fā)起HTTP GET請(qǐng)求, 使用<script>元素實(shí)現(xiàn)腳本操作HTTP可以跨域通信而不受限與同源策略. 通常, 使用基于<script>的Ajax傳輸協(xié)議時(shí), 服務(wù)器響應(yīng)采用JSON編碼的數(shù)據(jù)格式, 當(dāng)執(zhí)行腳本時(shí)候, JavaScript解析器能夠自動(dòng)將其解碼. 由于它使用JSON數(shù)據(jù)格式, 因此這種Ajax傳輸協(xié)議也叫做"JSONP". 所以使用jsonp技術(shù), 只需要設(shè)置<script>的src屬性, 并且插入到document中, 然后瀏覽器就會(huì)發(fā)送一個(gè)http請(qǐng)求以下載src屬性所執(zhí)行的url.
當(dāng)使用<script>元素調(diào)用數(shù)據(jù)時(shí), 響應(yīng)內(nèi)容必須用JavaScript函數(shù)名和圓括號(hào)包裹起來(lái)(也就是只能作為函數(shù)的參數(shù)), 而不是直接的一段json數(shù)據(jù):
response(
[1, 2, {"hello", "world"}]
)
為了可行期間, 我們必須通過(guò)某種方式告訴服務(wù), 它正在從一個(gè)<script>元素調(diào)用, 必須返回一個(gè)jsonp響應(yīng), 而不是普通的json, 這個(gè)可以通過(guò)在url中添加一個(gè)查詢參數(shù)來(lái)實(shí)現(xiàn): 例如, 追加"?json"(或者&json)
在實(shí)踐中, 支持jsonp的服務(wù)不會(huì)強(qiáng)制指定客戶端必須實(shí)現(xiàn)的回調(diào)函數(shù)名稱, 比如response. 相反它們使用查詢參數(shù)的值, 允許客戶端指定一個(gè)函數(shù)名,然后使用函數(shù)名去填充響應(yīng).
//根據(jù)指定的url發(fā)送一個(gè)json請(qǐng)求
//然后把解析得到的響應(yīng)數(shù)據(jù)傳遞給回調(diào)函數(shù)
//在url中添加一個(gè)名為jsonp的查詢參數(shù), 用于指定該請(qǐng)求的回調(diào)函數(shù)的名稱
function getJSONP(url, callback){
//為本次請(qǐng)求創(chuàng)建一個(gè)唯一的回調(diào)函數(shù)名稱
var cbnum = "cb"+getJSONP.counter++;
var cbname = "getJSONP."+cbnum; //作為jsonp函數(shù)的屬性
//將回調(diào)函數(shù)名稱以表單編碼的形式添加到url查詢部分中
if(url.indexOf("?") === -1){
url += "?jsonp="+cbname;
}else{
url += "&jsonp="+cbname;
}
//創(chuàng)建<script>用于發(fā)送請(qǐng)求
var script = document.createElement("script");
//定義被腳本執(zhí)行的回調(diào)函數(shù)
getJSONP[cbnum] = function(response){
try{
callback(response); //處理響應(yīng)
}
finally{
//刪除該函數(shù), 并移除相應(yīng)script元素
delete getJSONP[cbnum];
script.parentNode.removeChild(script);
}
}
//立即觸發(fā)http請(qǐng)求
script.src = url;
document.body.appendChild(script);
}
getJSONP.counter = 0;
當(dāng)使用<script>元素調(diào)用數(shù)據(jù)時(shí), 響應(yīng)內(nèi)容必須用JavaScript函數(shù)名和圓括號(hào)包裹起來(lái)(也就是只能作為函數(shù)的參數(shù)), 而不是直接的一段json數(shù)據(jù):
復(fù)制代碼 代碼如下:
response(
[1, 2, {"hello", "world"}]
)
為了可行期間, 我們必須通過(guò)某種方式告訴服務(wù), 它正在從一個(gè)<script>元素調(diào)用, 必須返回一個(gè)jsonp響應(yīng), 而不是普通的json, 這個(gè)可以通過(guò)在url中添加一個(gè)查詢參數(shù)來(lái)實(shí)現(xiàn): 例如, 追加"?json"(或者&json)
在實(shí)踐中, 支持jsonp的服務(wù)不會(huì)強(qiáng)制指定客戶端必須實(shí)現(xiàn)的回調(diào)函數(shù)名稱, 比如response. 相反它們使用查詢參數(shù)的值, 允許客戶端指定一個(gè)函數(shù)名,然后使用函數(shù)名去填充響應(yīng).
復(fù)制代碼 代碼如下:
//根據(jù)指定的url發(fā)送一個(gè)json請(qǐng)求
//然后把解析得到的響應(yīng)數(shù)據(jù)傳遞給回調(diào)函數(shù)
//在url中添加一個(gè)名為jsonp的查詢參數(shù), 用于指定該請(qǐng)求的回調(diào)函數(shù)的名稱
function getJSONP(url, callback){
//為本次請(qǐng)求創(chuàng)建一個(gè)唯一的回調(diào)函數(shù)名稱
var cbnum = "cb"+getJSONP.counter++;
var cbname = "getJSONP."+cbnum; //作為jsonp函數(shù)的屬性
//將回調(diào)函數(shù)名稱以表單編碼的形式添加到url查詢部分中
if(url.indexOf("?") === -1){
url += "?jsonp="+cbname;
}else{
url += "&jsonp="+cbname;
}
//創(chuàng)建<script>用于發(fā)送請(qǐng)求
var script = document.createElement("script");
//定義被腳本執(zhí)行的回調(diào)函數(shù)
getJSONP[cbnum] = function(response){
try{
callback(response); //處理響應(yīng)
}
finally{
//刪除該函數(shù), 并移除相應(yīng)script元素
delete getJSONP[cbnum];
script.parentNode.removeChild(script);
}
}
//立即觸發(fā)http請(qǐng)求
script.src = url;
document.body.appendChild(script);
}
getJSONP.counter = 0;
相關(guān)文章
詳解webpack-dev-server 設(shè)置反向代理解決跨域問(wèn)題
后端只負(fù)責(zé)接口,前端負(fù)責(zé)數(shù)據(jù)展示、邏輯處理。那么如何跨域?這篇文章主要介紹了webpack-dev-server 設(shè)置反向代理解決跨域問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04查看QQ是否在線狀態(tài)的網(wǎng)頁(yè)代碼
這個(gè)其實(shí)就是利用qq官方提供的東西,簡(jiǎn)單的通過(guò)圖片來(lái)測(cè)試是否在線,隱身也是不在線狀態(tài)。純粹學(xué)習(xí)使用。2010-04-04JavaScript Date對(duì)象詳解及時(shí)間戳和時(shí)間的相互轉(zhuǎn)換問(wèn)題
這篇文章主要介紹了JavaScript Date對(duì)象詳解及時(shí)間戳和時(shí)間的相互轉(zhuǎn)換問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-01-01JS端基于download.js實(shí)現(xiàn)圖片、視頻時(shí)直接下載而不是打開預(yù)覽
這篇文章主要介紹了JS端基于download.js實(shí)現(xiàn)圖片、視頻時(shí)直接下載而不是打開預(yù)覽,需要的朋友可以參考下2020-05-05原生js仿jquery實(shí)現(xiàn)對(duì)Ajax的封裝
大家都知道jquery在我們?nèi)粘i_發(fā)中的使用頻率非常高,但jquery說(shuō)到底還是對(duì)js的封裝,我們不能光會(huì)使用,只有知道了其中的遠(yuǎn)離才能更好的使用,所以這篇文章主要介紹的是原生js仿jquery實(shí)現(xiàn)對(duì)Ajax封裝的方法。2016-10-10JavaScript作用域深度剖析之動(dòng)態(tài)作用域
這篇文章主要為大家介紹了?JavaScript作用域?qū)W習(xí)之動(dòng)態(tài)作用域深度剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05