javascript
跨域之JSONP
為什么80%的碼農都做不了架構師?>>> ??
1 跨域及同源策略
1.1 什么是跨域
一般來說,如果你在開發中需要進行跨域操作(從一個非同源網站發送請求獲取數據),一般而言,你在瀏覽器控制臺看到的結果為:
XMLHttpRequest cannot load http://external-domain/service. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://my-domain’ is therefore not allowed access.
像這樣發送ajax請求會在瀏覽器中得到如下訪問受限的提示
<html> <head> <meta charset="utf-8" /> <script> function success(text) { var textarea = document.getElementById('test-response-text'); textarea.innerHTML = text; }function fail(code) { var textarea = document.getElementById('test-response-text'); textarea.innerHTML = 'Error code: ' + code; }function helloAjax() { var request = new XMLHttpRequest(); // 新建XMLHttpRequest對象request.onreadystatechange = function () { // 狀態發生變化時,函數被回調 if (request.readyState === 4) { // 成功完成// 判斷響應結果:if (request.status === 200) {// 成功,通過responseText拿到響應的文本://alert('request.responseText');return success(request.responseText);} else {// 失敗,根據響應碼判斷失敗原因://alert('request.status');return fail(request.status);} } else {console.log('continuing……'); } }// 發送請求: request.open('GET', 'http://api.money.126.net/data/feed/0000001,1399001,1399006?callback=refreshPrice'); request.send();alert('請求已發送,請等待響應...'); }</script> </head> <body> <div> <p id="test-response-text"></p> <p><button type="button" onclick="helloAjax()">刷新</button></p> </div> </body> </html>1.2 同源策略
????? 說到跨域就不得不提“同源策略”。同源策略是Web瀏覽器針對惡意的代碼所進行的措施,為了防止世界被破壞,為了保護世界的和平,Web瀏覽器,采取了同源策略,只允許腳本讀取和所屬文檔來源相同的窗口和文檔的屬性。那么,怎么判斷文檔來源是否相同呢?很簡單,看三個部分: 協議、主機、端口號。只要其中一個部分不同,則不同源。
1.3 跨域的應用場景
來自 home.example.com 的文檔里的腳本讀取 developer.example.com載入的文檔的屬性。
來自 home.example.com 的文檔里的腳本讀取 text.segmentfault.com載入的文檔的屬性
2 JSONP跨域
實際應用場景中不可避免地需要進行跨域操作,這時候“同源策略”就顯得過于苛刻。JSONP跨域GET請求是一個常用的解決方案。
2.1 概念介紹
?????? JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協議、端口)的資源。如果要進行跨域請求, 我們可以通過使用html的script標記來進行跨域請求(即利用在頁面中創建<script>節點的方法向不同域提交HTTP請求),并在響應中返回要執行的script代碼,其中可以直接使用JSON傳遞javascript對象。 這種跨域的通訊方式稱為JSONP。
?????? 假設在http://example1.com/index.php這個頁面中向http://example2.com/getinfo.php提交GET請求,我們可以將下面的JavaScript代碼放在http://example1.com/index.php這個頁面中來實現:
當GET請求從http://example2.com/getinfo.php返回時,可以返回一段JavaScript代碼,這段代碼會自動執行,可以用來負責調用http://example1.com/index.php頁面中的一個callback函數。
2.2 原理及實例
JSONP的最基本的原理是:
動態添加一個<script>標簽,而script標簽的src屬性是沒有跨域的限制的。這樣說來,這種跨域方式其實與ajax XmlHttpRequest協議無關了。
這樣其實"jQuery AJAX跨域問題"就成了個偽命題,jquery $.ajax方法名有誤導人之嫌。如果設為dataType: 'jsonp',這個$.ajax方法就和ajax XmlHttpRequest沒什么關系了,取而代之的則是JSONP協議。JSONP是一個非官方的協議,它允許在服務器端集成Script tags返回至客戶端,通過javascript callback的形式實現跨域訪問。
Jsonp的執行過程如下:
首先在客戶端注冊一個callback (如:'jsoncallback'), 然后把callback的名字(如:jsonp1236827957501)傳給服務器。注意:服務端得到callback的數值后,要用jsonp1236827957501(......)把將要輸出的json內容包括起來,此時,服務器生成 json 數據才能被客戶端正確接收。
然后以 javascript 語法的方式,生成一個function, function 名字就是傳遞上來的參數 'jsoncallback'的值 jsonp1236827957501 .
最后將 json 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
例1:
<html> <head> <meta charset="utf-8" /><script>function refreshPrice(data) {var p = document.getElementById('test-jsonp');p.innerHTML = '當前價格:' +data['0000001'].name +': ' + data['0000001'].price + ';' +data['1399001'].name + ': ' +data['1399001'].price + ';' +data['1399006'].name + ': ' +data['1399006'].price; } function getPrice() {varjs = document.createElement('script'),head = document.getElementsByTagName('head')[0];js.src = 'http://api.money.126.net/data/feed/0000001,1399001,1399006?callback=refreshPrice';head.appendChild(js); }</script> </head> <body> <div><p id="test-jsonp">當前價格:</p><p><button type="button" onclick="getPrice()">刷新</button></p> </div> </body> </html>通過參數callback定義回調函數名字為refreshPrice,服務端得到callback的數值為refreshPrice后,要用refreshPrice(......)把將要輸出的json內容包括起來,此時,服務器生成 json 數據才能被客戶端正確接收。
例2:
<html> <head> <meta charset="utf-8" /> <title>Test Jsonp</title> <script type="text/javascript"> function jsonpCallback(sb) { alert(sb['0000001'].name); } </script> <script type="text/javascript" src="http://api.money.126.net/data/feed/0000001,1399001,1399006?callback=jsonpCallback"></script> </head> <body> </body> </html>例3:
<html> <head> <meta charset="utf-8" /> <title>Untitled Page</title><script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script><script type="text/javascript">jQuery(document).ready(function(){$.ajax({type: "get",async: false,url: "http://api.money.126.net/data/feed/0000001,1399001,1399006",dataType: "jsonp",//jsonp: "zjg",//傳遞給請求處理程序或頁面的,用以獲得jsonp回調函數名的參數名(一般默認為:callback)//jsonpCallback:"flightHandler",//自定義的jsonp回調函數名稱,默認為jQuery自動生成的隨機函數名,也可以寫"?",jQuery會自動為你處理數據success: function(json){alert(json['0000001'].name);},error: function(){alert('fail');}});});</script></head><body></body></html>這里需重點說明下jquery中ajax的jsonp和jsonpCallback這兩個參數的含義
3 JSONP優缺點
JSONP的優點是:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中都可以運行,不需要XMLHttpRequest或ActiveX的支持;并且在請求完畢后可以通過調用callback的方式回傳結果。
JSONP的缺點則是:它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題。
?
參考:
http://www.w3school.com.cn/jquery/ajax_ajax.asp
https://segmentfault.com/a/1190000006908944?utm_source=tuicool&utm_medium=referral
http://www.nowamagic.net/librarys/veda/detail/224/
http://kb.cnblogs.com/page/139725/
http://www.cnblogs.com/know/archive/2011/10/09/2204005.html
http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499861493e7c35be5e0864769a2c06afb4754acc6000
轉載于:https://my.oschina.net/zjg23/blog/794933
總結
- 上一篇: transform插件
- 下一篇: canvas写的一个刮奖效果