JSONP跨域模擬百度搜索
目錄
- 一、什麼是ONP
- 二、JSONP跨域請求
- 三、模擬百度搜索
- 四、JSONP缺點
一、什麼是JSONP
JSONP
是JSON with padding
(填充式JSON或引數式JSON)的簡寫,是應用JSON的一種新方法,在後來的Web服務中非常流行,JSONP看起來與JSON差不多,只不過是被包含在函式中呼叫的JSON,就像下面這樣:
callback({"name": "王歡"});
SONP由兩部分組成:回撥函式和資料。回撥函式是當響應到來時應該在頁面 中呼叫的函式。回撥函式的名字一般是在請求中指定的。而資料就是傳入回撥函式中的JSON資料。下面就是一個典型的JSONP請求。
https://freegeoip.net/json/?callback=handleResponse
這個URL是在請求一個JSONP
地理定位服務,通過查詢字串來指定JSONP服務的回撥引數是很常見的,就像上面的URL所示,這裡指定的回撥函式的名字叫做:handleResponse()
JSONP是通過動態
<script>
元素來使用的,使用時可以為src屬性指定一個跨域URL。可以不受限制的從其他域載入資源,因為JSONP是有效的程式碼,所以在請求完成後,即在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>
假設前端已經http://www.cppcns.com把函式名告訴了後端,後端就可以呼叫這個getData()
,並且可以傳遞信wOeJa息。在jsonp.html
就可以請求到下述jsonp.js
檔案。
getData({ name: '小王',age: 20 })
執行得到結果為:
得到了一個Object
物件,就是我們所傳遞的資料。
那麼,我們如何告訴伺服器getData()
這個函式呢?如果我們每次都固定是getData(),
我們的開發會很死板,就不能定義其他函式名字。實際上,我們可以通過get請求將我們前端定義的函式名字通過引數告訴後端,後端動態生成這樣的一個指令碼檔案並返回給函式的呼叫就可以。
百度就有一個這樣的介面,我們一起來看看。
開啟瀏覽器百度頁面,開啟除錯工具,看一下NETwork
標籤下面會監聽所有關於瀏覽器向伺服器傳送的http請求並檢視資料。
在搜尋框鍵入“b”,請求如圖:
請求得到的關鍵字為:
這裡的callback
函式其實是生成的一個全域性函式。得到這個URL
後,我們可以儲存其有用的資訊,並將回撥函式換成別的函式:
https://www.baidu.com/sugrec?pre=1&wd=b&req=2&csor=1&cb=getData();
將其輸入到位址列中進行測試:
可以發現,這個回撥函式就變成了我們設定的。
三、模擬百度搜索
我們現在就可以通過這個介面去發生JSON來模擬一下百度搜索頁面。
我們定義一個全域性變數作為接收資料的函式,data就是接收到的資料,一旦getdata()
函式被呼叫,說明我們我們的Jsonp函式就傳送完成,此時可以通過removeChild()
刪除script標籤,這樣就可以實現每當我們傳送一次請求,script
標籤在接收到資料後就會被刪除,在資料處理的時候,getData()
返回給我們的是一個物件,物件裡面有一個關鍵字g,裡面對應的是一個數組,數組裡面是字串,我們先將這個陣列遍歷,然後根據每個元素生成一個li加到input下面的ul就可以,先將ul裡面的html清空,這樣的話,每次請求的li都是全新的,當keyup
出來的時候,首先取到當前input
的value值並呼叫getdata()
函式,將wd傳進來,就實現了jsonp傳遞資料的過程。
程式碼如下:
<!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'); } } //動態生成script指令碼 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事件處理程式,但目前還沒有得到任何瀏覽器的支援。為此,開發人員不得不使用計時器檢測指定時間內是否接收到了響應。但是畢竟不是每個使用者的上網速度和頻寬都一樣,所以操作起來也不盡人意。
到此這篇關於JSONP跨域模擬百度搜索的文章就介紹到這了,更多相關JSONP跨域模擬百度搜索內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!