標籤:
眾所周知:在開發過程中,有時候需要用戶端從伺服器接收或向伺服器發送一些資料;如果使用普通的ajax,則會遇到跨域訪問無許可權的問題。
要解決這個問題,就需要瞭解一下jsonp了:
1. ajax請求普通檔案存在跨域訪問無許可權的問題。
2. 但是當遠程請求js檔案時則不受跨域影響,而且只要是有src屬性的標籤都有跨域的能力
3. 如果想通過純web端跨域訪問資料就只有一種可能,就是在服務端設法把資料封裝進js檔案中,給用戶端
4. 剛好json的資料格式是被js支援的
有了以上4點,解決方案就呼之欲出了,先來個簡單的例子(django):
首先建立一個api.js:
alert(‘我在伺服器上!‘)
然後在index頁面上載入js:
{% load staticfiles %}<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>首頁</title></head><body> <h1>我是首頁</h1> <script src="{% static ‘jsnpapp/api.js‘ %}"></script></body></html>
接下來啟動伺服器訪問一下:
這樣似乎沒有什麼意義,它們在同一個域中! 那現在我們在本地案頭上建立立一個index.html檔案來類比跨域:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>首頁</title></head><body> <h1>我是首頁</h1> <script src="http://localhost:8000/static/jsnpapp/api.js"></script></body></html>
可以看到,在本地的index.html中調用了遠程伺服器的api.js檔案;下面用瀏覽器開啟本地index.html:
可以看到遠程伺服器的js被本地執行了。
現在改進一下:
在本地index.html中定義一個函數:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>首頁</title></head><body> <h1>我是首頁</h1> <script> var localHandler = function(data) { alert(‘我是本地的函數,我要跨域調用,遠程js帶來的資料是:‘+data.result); } </script> <script src="http://localhost:8000/static/jsnpapp/api.js"></script></body></html>
伺服器上的api.js也修改一下:
localHandler({"result":"我是遠程js帶來的資料"});
有點意思,遠程伺服器要執行本地的函數;我們用瀏覽器開啟本地index.html看看效果:
很完美,本地的函數被遠程伺服器跨域執行了,而且本地也得到了伺服器發來的資料。這樣一個跨域就實現了。 但問題是,這些資料都是寫死的,
怎麼讓遠程伺服器端知道本地的函數名呢,然後返回不同的資料呢?畢竟服務端是要服務很多客戶的,這些客戶的需求是不一樣的。
如果用戶端能傳遞一個參數給伺服器,告訴伺服器“我要XX函數的資料,請返回給我”, 於是服務端就可以按照用戶端的請求響應資料了。
再改進一下,動態響應用戶端
先修改一下本地的Index.html, 為了滿足各種需求,那麼請求url的參數就不能被寫死,要動態產生;可以使用動態產生<script>標籤的方法來實現:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>首頁</title></head><body> <h1>我是首頁</h1> <script> var localHandler = function(data) { alert(‘我是本地的函數,我要跨域調用,遠程js帶來的資料是:‘+data.result); } // 提供jsonp服務的url地址(不管是什麼類型的地址,最終產生的傳回值都是一段javascript代碼) var url = "http://localhost:8000/jsnpapp/api?code=1&callback=localHandler"; // 建立script標籤,設定其屬性 var script = document.createElement(‘script‘); script.setAttribute(‘src‘, url); // 把script標籤加入head,此時調用開始 document.getElementsByTagName(‘head‘)[0].appendChild(script); </script></body></html>
服務端,首先要建立一個url, 然後views, 服務端接收到用戶端發來的參數後,動態產生了localHandler這個函數的javascript代碼並返回給用戶端:
urlpatterns = [ url(r‘^api/‘, views.base_api), url(r‘^index/$‘, views.index),]
def base_api(request): if request.method == "GET": code = request.GET.get(‘code‘) callback = request.GET.get(‘callback‘) if code == ‘1‘: msg = "%s({‘result‘:‘你給我1, 我就給你1111‘})" % callback print(‘msg:‘, msg) return HttpResponse(msg) return HttpResponse(‘我是伺服器!‘)
瀏覽器運行index.html :
用戶端成功擷取到了服務端返回的資料。jsonp的執行過程全部完成。
jsonp的理解