1. 程式人生 > >跨站請求資料jsonp手寫原生js程式碼實現

跨站請求資料jsonp手寫原生js程式碼實現

JSONP

 --來自百度百科

JSONP(JSON with Padding)是JSON的一種“使用模式”,可用於解決主流瀏覽器的跨域資料訪問的問題。由於同源策略,一般來說位於 server1.example.com 的網頁無法與不是 server1.example.com的伺服器溝通,而 HTML 的<script> 元素是一個例外。利用 <script> 元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並不是 JSON,而是任意的JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。

關於HTML幾種標籤能否獲取資料的說明:

<!-- 早期用於統計連結,支援跨域但是無法實現獲取服務端返回的資料 -->
<img src="http://www.baidu.com?id=xxx">
<!-- 支援,可以接受服務端資料,但過程複雜 -->
<iframe src="http://www.baidu.com?id=xxx" frameborder="0"></iframe>
<!-- 會在css處理階段報錯 -->
<link rel="stylesheet" href="http://www.baidu.com?id=xxx">
<!-- script可以接受資料並處理 -->
<script src="http://www.baidu.com?id=xxx"></script>
<!-- callback({}) -->

原生js實現jsonp跨站獲取資料:

var jsonp = function(url,data,callback){
// 回撥函式+時間戳
var cbName = 'callback_' + new Date().getTime();
// 暴露全域性函式給window
// 判讀查詢字串最後一位是否為?或者是&
var queryString = url.indexOf('?') == -1 ? '?' : '&';
// 遍歷傳進來的data實參賦值給查詢字串
for(var k in data){
queryString += k + '=' + data[k] + '&';
}
// 查詢字串加上回調函式
queryString += 'callback=' + cbName;
// 建立script標籤
var ele = document[0].createElement('script');
// 給script標籤新增src屬性值
ele.src = url + queryString;
window[cbName] = function(data){
callback(data);
document[0].body.removeChild(ele);
};
// 新增到body尾部
document[0].body.appendChild(ele);
}

使用方法:

$jsonp('http://api.douban.com/v2/movie/in_theaters',{
	'count':1
},function(data){
	document.getElementsByTagName('body')[0].innerHTML = JSON.stringify(data);
})
html結構:
<div id="result"></div>

完整程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>jsonp</title>
</head>
<body>
	<div id="result"></div>
<script>
(function(window,document,undefined){
var jsonp = function(url,data,callback){
// 回撥函式+時間戳
var cbName = 'callback_' + new Date().getTime();
// 暴露全域性函式給window
// 判讀查詢字串最後一位是否為?或者是&
var queryString = url.indexOf('?') == -1 ? '?' : '&';
// 遍歷傳進來的data實參賦值給查詢字串
for(var k in data){
queryString += k + '=' + data[k] + '&';
}
// 查詢字串加上回調函式
queryString += 'callback=' + cbName;
// 建立script標籤
var ele = document[0].createElement('script');
// 給script標籤新增src屬性值
ele.src = url + queryString;
window[cbName] = function(data){
callback(data);
document[0].body.removeChild(ele);
};
// 新增到body尾部
document[0].body.appendChild(ele);
}
//jsonp函式暴露給window
window.$jsonp = jsonp;
})(window,document,undefined);
</script>
<script>
$jsonp('http://api.douban.com/v2/movie/in_theaters',{
	'count':1
},function(data){
	document.getElementsByTagName('body')[0].innerHTML = JSON.stringify(data);
})
</script>
</body>
</html>
歡迎大家提意見