<script>元素的src屬性能設置URL並發起HTTP GET請求, 使用<script>元素實現腳本操作HTTP可以跨域通信而不受限與同源策略. 通常, 使用基於<script>的Ajax傳輸協議時, 服務器響應采用JSON編碼的數據格式, 當執行腳本時候, JavaScript解析器能夠自動將其解碼. 由於它使用JSON數據格式, 因此這種Ajax傳輸協議也叫做"JSONP". 所以使用jsonp技術, 只需要設置<script>的src屬性, 並且插入到document中, 然後浏覽器就會發送一個http請求以下載src屬性所執行的url.
當使用<script>元素調用數據時, 響應內容必須用JavaScript函數名和圓括號包裹起來(也就是只能作為函數的參數), 而不是直接的一段json數據:
復制代碼 代碼如下:
response(
[1, 2, {"hello", "world"}]
)
為了可行期間, 我們必須通過某種方式告訴服務, 它正在從一個<script>元素調用, 必須返回一個jsonp響應, 而不是普通的json, 這個可以通過在url中添加一個查詢參數來實現: 例如, 追加"?json"(或者&json)
在實踐中, 支持jsonp的服務不會強制指定客戶端必須實現的回調函數名稱, 比如response. 相反它們使用查詢參數的值, 允許客戶端指定一個函數名,然後使用函數名去填充響應.
復制代碼 代碼如下:
//根據指定的url發送一個json請求
//然後把解析得到的響應數據傳遞給回調函數
//在url中添加一個名為jsonp的查詢參數, 用於指定該請求的回調函數的名稱
function getJSONP(url, callback){
//為本次請求創建一個唯一的回調函數名稱
var cbnum = "cb"+getJSONP.counter++;
var cbname = "getJSONP."+cbnum; //作為jsonp函數的屬性
//將回調函數名稱以表單編碼的形式添加到url查詢部分中
if(url.indexOf("?") === -1){
url += "?jsonp="+cbname;
}else{
url += "&jsonp="+cbname;
}
//創建<script>用於發送請求
var script = document.createElement("script");
//定義被腳本執行的回調函數
getJSONP[cbnum] = function(response){
try{
callback(response); //處理響應
}
finally{
//刪除該函數, 並移除相應script元素
delete getJSONP[cbnum];
script.parentNode.removeChild(script);
}
}
//立即觸發http請求
script.src = url;
document.body.appendChild(script);
}
getJSONP.counter = 0;