前言:有時候一忙起來就沒了時間觀念,原來我已經有十多天沒寫博客了。一直想作跨域方面的嘗試,無奈最近準備校招沒時間動動手。今天就先講講JSONP吧,昨晚還在研究QQ空間日誌裏面網絡圖片的問題呢,我發現日誌還提供了HTML模式,咱們能夠利用img標籤的src屬性實現跨域請求,從本身的服務器裏提取動態內容。php
JSONPjquery
在講實現以前,咱們先來看看何爲JSONP。如下是維基百科的解釋:web
JSONP or "JSON with padding" is a communication technique used in JavaScript programs running in web browsers to request data from a server in a different domain, something prohibited by typical web browsers because of the same-origin policy. JSONP takes advantage of the fact that browsers do not enforce the same-origin policy on <script>
tags. Since it works through <script>
tags, JSONP supports only the GET request method. There are significant security implications and risks associated to using JSONP; unless you have no choice, CORS is usually the better choice.ajax
我粗陋翻譯一下:JSONP又稱JSON with padding,它是用在瀏覽器上運行的JS程序裏的一項交互技術,目的是爲了從不一樣的服務器域名上請求數據。因爲同源政策的限制,部分功能會受到瀏覽器的禁止。JSONP利用的是瀏覽器不會對<script>標籤實施同源政策的狀況。又由於它是經過<script>做用的,因此JSONP只支持GET請求方式。但值得注意的是,使用JSONP會存在安全隱患和危險。CORS(跨域資源共享,Cross-Origin Resource Sharing)是一個更爲經常使用的佳選,除非你沒得選。json
解釋: 跨域
簡單來講就是,通常狀況下,在本域名的頁面想要獲取其餘域名下的數據是會受到限制的。可是在HTML頁面中的<script>(img,iframe亦可)就突破了這種限制,能夠經過src屬性來訪問其餘域名並得到返回的數據,但這種方法並不安全,只能經過GET方法獲取。瀏覽器
其實咱們日常稍加留意,就不難發現其實咱們日常在頁面中使用CDN也是這個原理,咱們的頁面一樣能夠訪問其餘服務器上的JS文件。緩存
如咱們經常使用的百度CDN,咱們一般在<head>裏面加上是<script>標籤就可使用其餘服務器的CDN。安全
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js"></script>服務器
只不過稍有不一樣的是如今變爲向服務器運行文件請求數據,而後再以JavaScript的形式返回。
客戶端實現:
JSONP是一種非正式傳輸協議,具體傳輸內容以及格式能夠由用戶本身定義。不過我以爲JSONP可能會在ES6中新增也說不定哦,到時候可能會規範傳輸格式。JSONP其中有一個要點就是容許用戶傳遞一個callback參數給服務端,而後服務端輸出的數據做爲callback的參數再一併返回到客戶端頁面,最後根據參數在客戶端頁面執行這個回調函數,最終達到返回數據並處理的目的。
代碼形式以下:
1 <head> 2 <meta charset="UTF-8"> 3 <title>JSONP</title> 4 <script type="text/javscript"> 5 var cbFn = function(str){ 6 alert(str); 7 } 8 </script> 9 <script src="http://www.sp0.baidu.com?data=value&cb=cbFn"></script> 10 </head>
首先要預約義一個回調函數,用於處理返回數據;其次請求數據的<script>標籤的src要傳遞請求參數以及回調的函數名字到後臺,這一點要溝通協調好。
因爲在實際應用中請求地址、請求參數以及次數都是不固定的,因此咱們要把JSONP封裝成一個函數,加強靈活性和複用性。
1 var s1; 2 function jsonp(url,data,cb){ 3 data.cb = cb?cb:"callback"; 4 data.t = new Date().getTime(); 5 for (var i in data){ 6 var str = i+"="+data[i]; 7 arr.push(str); 8 } 9 var str = url+"?"+arr.join("&"); 10 var headEl = document.getElementsByTagName("head")[0]; 11 if (s1){ 12 headEl.removeChild(s1); 13 } 14 s1 = document.createElement("script"); 15 s1.src = str; 16 headEl.appendChild(s1);
17 }
代碼解釋:首先給傳遞的數據中插入一個回調函數名和一個新的時間參數值,讓後臺獲取你要回調的函數名以及防止調用緩存。接下來就是判斷以前已是否發送過JSONP請求,若是存在,則刪除重建。
服務端實現:
假設我在客戶端執行了如下請求
1 jsonp("http://www.chengguanhui.com/test.php",{ 2 name:"ray", 3 age:23 4 },"cbFn"); 5 6 cbFn(str){ 7 alert(str); 8 }
那麼HTTP傳遞的URL爲http://www.chengguanhui.com/test.php?name=ray&age=23cb=cbFn&t=242566(某個不定時間值)
PHP代碼:
1 <?php 2 require_once("common.php"); 3 $name = $_GET['name']; 4 $age = $_GET['age']; 5 $cb = $_GET['cb']; 6 $str = $name.$age; 7 echo $cb."(".$str.")"; 8 ?>
客戶端接收到cbFn("ray23")並彈出對應內容。
JQ實現:
$.ajax(url,[settings])
1 $.ajax({ 2 type: "get", 3 url: "http://www.chengguanhui.com/test.php", 4 dataType: "jsonp", 5 data: "name=ray&age=23", 6 jsonp: "callback",//傳遞給請求處理程序或頁面的,用以得到jsonp回調函數名的參數名(通常默認爲:callback) 7 jsonpCallback:"handleFn",//自定義的jsonp回調函數名稱,默認爲jQuery自動生成的隨機函數名,也能夠寫"?",jQuery會自動爲你處理數據 8 success: function(json){ 9 alert(json.name+json.age); 10 }, 11 error: function(){ 12 alert('fail'); 13 } 14 }); 15 });
$.getJSON(url,data,callback)
1 $.getJSON("http://www.chengguanhui.com/test.php",//若是請求值固定時,能夠省略data參數而直接寫在url參數裏。 2 { 3 name:ray, 4 age:23 5 }, 6 function(data){ 7 $.each(data.items, function(i,item){ 8 alert(i+item); 9 }); 10 });
說明:原創文章,轉載全文內容或非翻譯內容時,請註明出處與做者。謝謝。