JSONP跨域
- 一、什么是JSONP
- 二、JSONP跨域請求
- 三、模擬百度搜索
- 四、JSONP缺點
一、什么是JSONP
JSONP是JSON with padding(填充式JSON或引數式JSON)的簡寫,是應用JSON的一種新方法,在后來的Web服務中非常流行,JSONP看起來與JSON差不多,只不過是被包含在函式中呼叫的JSON,就像下面這樣:
callback({"name": "投訓"});
JSONP由兩部分組成:回呼函式和資料,回呼函式是當回應到來時應該在頁面 中呼叫的函式,回呼函式的名字一般是在請求中指定的,而資料就是傳入回呼函式中的JSON資料,下面就是一個典型的JSONP請求,
https://freegeoip.net/json/?callback=handleResponse
這個URL是在請求一個JSONP地理定位服務,通過查詢字串來指定JSONP服務的回呼引數是很常見的,就像上面的URL所示,這里指定的回呼函式的名字叫做:handleResponse()
JSONP是通過動態<script>元素來使用的,使用時可以為src屬性指定一個跨域URL,可以不受限制的從其他域加載資源,因為JSONP是有效的JavaScript代碼,所以在請求完成后,即在JSONP回應加載到頁面中以后,就會立即執行,
二、JSONP跨域請求
我們知道,同源策略是瀏覽器的一種安全機制,所謂的源是指協議、域名和埠號,當我們的腳本在運行時,瀏覽器會檢測它所執行的腳本和他所取得的的資料與我們HTML頁面是否相同,如果相同,就是同源的,會進行成功的請求,如果他們的源不相同,就是跨域請求,在默認情況下,瀏覽器是不支持跨域請求的,那么如果我們想要跨域請求,該如何操作呢?
script標簽是不受同源策略的限制的,即我們在請求script腳本的時候,無論是在HTML所在的服務器還是其他服務器,它都可以請求到,所以我們就利用script標簽的這種性質來進行資料的跨域請求,就來看看JSONP是如何進行跨域請求的,
首先,我們請求一段script代碼,這段代碼里如果它能呼叫我們所指定的一個函式,并將資料作為實參傳遞進來,那么只要我們定義了這個函式并定義了形參,形參就會接收到他的實參來得到資料,舉個例子:
假設在腳本中定義了一個getData(data),如果現在請求一個腳本,這個腳本能夠呼叫getData()這個函式,并將data 作為實參傳遞進來,那形參收到的資料就可以進行相應的處理,
<script>
function getData(data){
console.log(data);
}
var script = document.createElement('script');
script.id = 'jsonp';
script.src = 'jsonp.js';
document.body.appendChild(script);
</script>
假設前端已經把函式名告訴了后端,后端就可以呼叫這個getData(),并且可以傳遞資訊,在jsonp.html就可以請求到下述jsonp.js檔案,
getData({
name: '小王',
age: 20
})
運行得到結果為:

得到了一個Object物件,就是我們所傳遞的資料,
那么,我們如何告訴服務器getData()這個函式呢?如果我們每次都固定是getData(),我們的開發會很死板,就不能定義其他函式名字,實際上,我們可以通過get請求將我們前端定義的函式名字通過引數告訴后端,后端動態生成這樣的一個腳本檔案并回傳給函式的呼叫就可以,
百度就有一個這樣的介面,我們一起來看看,
打開瀏覽器百度頁面,打開除錯工具,看一下NETwork標簽下面會監聽所有關于瀏覽器向服務器發送的http請求并查看資料,
在搜索框鍵入“b”,請求如圖:

請求得到的關鍵字為:

這里的callback函式其實是jquery生成的一個全域函式,得到這個URL后,我們可以保存其有用的資訊,并將回呼函式換成別的函式:
https://www.baidu.com/sugrec?pre=1&wd=b&req=2&csor=1&cb=getData();
將其輸入到地址欄中進行測驗:

可以發現,這個回呼函式就變成了我們設定的,
三、模擬百度搜索
我們現在就可以通過這個介面去發生JSON來模擬一下百度搜索頁面,
代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
position: relative;
width: 600px;
height: 40px;
}
input {
width: 500px;
height: 40px;
border: 2px solid #4E6EF2;
}
button{
position: absolute;
left: 411px;
top: 0;
width: 95px;
height: 44px;
background-color: #4E6EF2;
border: none;
font-size: 18px;
color: white;
}
ul{
position: relative;
left: -40px;
top: -10px;
width: 411px;
height: 400px;
}
li{
height: 40px;
width: 411px;
line-height: 40px;
font-size: 16px;
list-style: none;
}
</style>
</head>
<body>
<div>
<input type="text" value =''>
<button>百度一下</button>
</div>
<ul></ul>
<script src="jquery.js"></script>
<script>
function getData(data){
var script = document.querySelector('#jsonp');
script.parentNode.removeChild(script);
$('ul').html('');
for(var i =0;i<data.g.length;i++){
$('<li>'+data.g[i].q +'</li>').appendTo('ul');
}
}
function getList(wd){
var script = document.createElement('script');
script.id = 'jsonp';
script.src = 'https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=26350&req=2&csor=1&cb=getData&wd='+wd;
document.body.appendChild(script);
}
var ipt = document.querySelector('input');
ipt.addEventListener('keyup',function(){
var wd = this.value;
getList(wd);
console.log(wd);
})
</script>
</body>
</html>
效果為:

四、JSONP缺點
JSONP之所以在開發人員中極為流行,是因為它非常簡單易用,不過他也有兩點不足:
- 首先,JSONP是從其他域中加載執行代碼,如果其他域不安全,很可能會在回應中夾帶一些惡意代碼,而此時除了完全放棄JSONP呼叫之外,沒有辦法追究,
- 其次,要確定JSONP請求是否失敗并不容易,雖然HTML5給
<script>元素新增了一個onerror事件處理程式,但目前還沒有得到任何瀏覽器的支持,為此,開發人員不得不使用計時器檢測指定時間內是否接收到了回應,但是畢竟不是每個用戶的上網速度和帶寬都一樣,所以操作起來也不盡人意,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/377099.html
標籤:其他
上一篇:vue-element-admin 登出切換用戶后重新登錄跳轉404頁面Bug-解決記錄
下一篇:react、vue專案熟悉技巧
