javascript
JSONP的诞生、原理及应用实例
問題:
頁面中有一個按鈕,點擊之后會更新網頁中的一個盒子的內容。
Ajax可以很容易的滿足這種無須刷新整個頁面就可以實現數據變換的需求。
但是,Ajax有一個缺點,就是他不允許跨域請求資源。
如果我的代碼在codepen上,我不能將我的數據放到codepen網站上,那么我只能放到我自己的服務器中,這樣的話,就無法通過Ajax訪問到這個數據了。
解決:
想要實現這種跨域資源請求,有很多解決辦法,列舉出一部分:
?
JSONP的誕生及原理:
jsonp的原理其實和第二種解決方法一模一樣,只不過他更加方便,然后這種跨域溝通的手段就被賦予了一個名字“JSONP”。
所以首先要弄懂第二種方式是怎么工作的:
原理:如果一個頁面加載了一個外來的JS文件,瀏覽器就會自動執行這個文件中的代碼。
所以假如localhost想要使用jsonhost上面的一個JSON數據,localhost就可以讓jsonhost來幫他完成這件事情,jsonhost提供給他一個js文件,往要調用的函數中傳入需要的數據,結果是和localhost自己調用函數的效果一模一樣了。
jsonhost:
<script type="text/javascript">
? ?var json='["customername1","customername2"]';
? ?callbackFunction(json);?
</script>
localhost:
<script type="text/javascript">? ?var json='["customername1","customername2"]';
? ?callbackFunction(json);?
</script>
<script type="text/javascript">function callbackFunction(result){var html = '<ul>';for(var i = 0; i < result.length; i++){html += '<li>' + result[i] + '</li>';}html += '</ul>';document.getElementById('divCustomers').innerHTML = html;} </script>
這樣,localhost就已經可以使用jsonhost中的數據了。
然后localhost說,我希望可以在我的用戶點擊一次按扭時,就執行一遍callbackFunction(json),而不是頁面加載后執行一次。
于是他就需要動態的創建<script>標簽:
function callbackFunction(result) {var html = '<ul>';for(var i = 0; i < result.length; i++){html += '<li>' + result[i] + '</li>';}html += '</ul>';document.getElementById('divCustomers').innerHTML = html; } $(".btn").click(function(){var script = document.createElement('script');script.setAttribute('src', "http://jsonhost/json.js");document.getElementsByTagName('header')[0].appendChild(script); });這樣完成之后,效果就和用Ajax異步請求一樣了。
到這里,故事仿佛就要這樣結束了,但是突然有一天,另一個otherhost跑來和jsonhost說,他想要通過jsoncallbackFunction處理json,jsonhost就很為難,于是他們聚在一起,想要找到一個辦法,可以不需要全部使用同一個函數名,也可以獲取同一個數據。
最終他們想到了一個完美的辦法——jsonhost用的函數名用一個變量代替,localhost和otherhost請求數據的時候,傳入這個變量名,這樣就可以各自決定各自使用的函數名了。
jsonhost:
<?php header('Content-type: application/json'); //告訴接收數據的對象此頁面輸出的是json數據$json = '["customername1","customername2"]';echo $_GET['callback'] . "(" . $json . ")"; ?>localhost:
<script type="text/javascript">function getJson(url,funName){var script = document.createElement('script');script.setAttribute('src', url+funName);document.getElementsByTagName('head')[0].appendChild(script);}function callbackFunction(result){var html = '<ul>';for(var i = 0; i < result.length; i++){html += '<li>' + result[i] + '</li>';}html += '</ul>';document.getElementById('divCustomers').innerHTML = html;}$(".btn").click(function(){getJson("http://jsonhost/jsonp.php?jsoncallback=","callbackFunction");});</script>otherhost:
<script type="text/javascript">function getJson(url,funName){var script = document.createElement('script');script.setAttribute('src', url+funName);document.getElementsByTagName('head')[0].appendChild(script);}function jsoncallbackFunction(result){console.log(result);}$(".btn").click(function(){getJson("http://jsonhost/jsonp.php?jsoncallback=","jsoncallbackFunction");});</script>這樣一來,使用什么函數名都是不同host自己的事情,他們互不干擾,jsonhost也不用操心這件事,專心提供數據就可以了。其他host也紛紛前來獲取json。于是這種模式被廣泛使用,然后這種通信方式就被命名為“JSONP”。
?
如果用jQuery的話,就不用自己命名函數并傳遞給參數了,因為這個函數名一點也不重要,他只是個代號而已,jQuery會幫我們自動生成一個函數名,然后將得到的數據傳給這個函數。jQuery還會幫我們創建script標簽, 我們只要關心如何處理這個數據就好了。
<script src="http://apps.bdimg.com/libs/jquery/1.8.3/jquery.js"></script> <script>$.getJSON("http://jsonhost/jsonp.php?jsoncallback=?", function(data) {var html = '<ul>';for(var i = 0; i < data.length; i++){html += '<li>' + data[i] + '</li>';}html += '</ul>';$('#divCustomers').html(html);}); </script>jQuery把JSONP封裝到Ajax里面,但本質上這兩種技術是完全不同的。
JSONP的原理是,當前網頁動態執行異域返回的js代碼,這個代碼是個執行請求數據的函數。瀏覽器執行這個函數,效果和當前域獲得數據執行函數是一樣的。
?
應用實例:
知道了原理之后,迫不及待的想要用一下JSONP來獲取數據。這里用PHP來實現。
首先,需要有個服務器,如果沒有服務器的話,可以使用wampserver軟件模擬一個,這個軟件還會建立一個集成環境,可以運行PHP文件。點擊查看wampserver教程
有了自己的服務器和PHP運行環境之后,就可以開始了。想要在codepen上獲取本地數據。
本機PHP:
<?php header('Content-type: application/json'); //告訴接收數據的對象此頁面輸出的是json數據 $quotes = '[{"quote": "If you can\'t get rid of the skeleton in your closet, you\'d best teach it to dance.","author": "George Bernard Shaw"},{"quote": "We\'ll always have Paris.","author": "Casablanca"},{"quote": "A mathematician is a device for turning coffee into theorems.","author": "Paul Erdos"},{"quote": "Do, or do not. There is no \'try\'.","author": "Star Wars: Empire Strikes Back"},{"quote": "Some cause happiness wherever they go; others, whenever they go.","author": "Oscar Wilde"},{"quote": "Problems worthy of attack prove their worth by fighting back.","author": "Paul Erdos"},{"quote": "Maybe this world is another planet\'s Hell.","author": "Aldous Huxley"}]';echo $_GET['callback'] . "(" . $quotes . ")"; ?>codepen上的js:
function update(){var index=Math.floor(Math.random()*11);$.getJSON("http://localhost/quotes.php?callback=?",function(data){var num=Math.floor(Math.random()*6);$(".wrap").fadeOut(600,function(){$(".quo").html(data[num].quote);$(".auth").html(data[num].author);$("body, .quote-box button").css("background-color",colors[index]);$(".wrap").css("color",colors[index]);}).fadeIn(600);}); }$(document).ready(function(){update();$(".update").click(update); });點擊查看在線demo,必須將本機模擬成服務器并建立PHP環境并添加了PHP文件才能運行。
而且要注意把codepen的https改成http。
成功之后可以看到,發送的請求中,傳給callback的是一個jQuery自動生成的函數:
返回的也是這個函數調用數據:
?
如果不想自己配置的話,可以應用其他網站提供的API,實現原理是一樣的。demo
?
參考:
- JSONP 教程
- 《jQuery基礎教程》
- 說說JSON和JSONP,也許你會豁然開朗,含jQuery用例
轉載于:https://www.cnblogs.com/LiveWithIt/p/JSONP.html
總結
以上是生活随笔為你收集整理的JSONP的诞生、原理及应用实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 基础篇:介绍
- 下一篇: Notepad++如何编译、运行Java