天天看點

jsonp跨域請求之jQuery的ajax jsonp的使用解惑

JSONP的優點是:它不像XMLHttpRequest對象實作的Ajax請求那樣受到同源政策的限制;它的相容性更好,在更加古老的浏覽器中都 可以運作,不需要XMLHttpRequest或ActiveX的支援;并且在請求完畢後可以通過調用callback的方式回傳結果。

JSONP的缺點則是:它隻支援GET請求而不支援POST等其它類型的HTTP請求;它隻支援跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題。

===============================================================================================================

JSONP原理

JSONP的最基本的原理是:動态添加一個<script>标簽,而script标簽的src屬性是沒有跨域的限制的。這樣說來,這種跨域方式其實與ajax XmlHttpRequest協定無關了。

這樣其實"jQuery AJAX跨域問題"就成了個僞命題,jquery $.ajax方法名有誤導人之嫌。

如果設為dataType: 'jsonp',這個$.ajax方法就和ajax XmlHttpRequest沒什麼關系了,取而代之的則是JSONP協定。JSONP是一個非官方的協定,它允許在伺服器端內建Script tags傳回至用戶端,通過javascript callback的形式實作跨域通路。

JSONP即JSON with Padding。由于同源政策的限制,XmlHttpRequest隻允許請求目前源(域名、協定、端口)的資源。如果要進行跨域請求, 我們可以通過使用html的script标記來進行跨域請求,并在響應中傳回要執行的script代碼,其中可以直接使用JSON傳遞javascript對象。 這種跨域的通訊方式稱為JSONP。

jsonCallback 函數jsonp1236827957501(....):是浏覽器用戶端注冊的,擷取跨域伺服器上的json資料後,回調的函數

Jsonp的執行過程如下:

首先在用戶端注冊一個callback (如:'jsoncallback'), 然後把callback的名字(如:jsonp1236827957501)傳給伺服器。注意:服務端得到callback的數值後,要用jsonp1236827957501(......)把将要輸出的json内容包括起來,此時,伺服器生成 json 資料才能被用戶端正确接收。

然後以 javascript 文法的方式,生成一個function, function 名字就是傳遞上來的參數 'jsoncallback'的值 jsonp1236827957501 .

最後将 json 資料直接以入參的方式,放置到 function 中,這樣就生成了一段 js 文法的文檔,傳回給用戶端。

用戶端浏覽器,解析script标簽,并執行傳回的 javascript 文檔,此時javascript文檔資料,作為參數, 傳入到了用戶端預先定義好的 callback 函數(如上例中jquery $.ajax()方法封裝的的success: function (json))裡。

可以說jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一緻的(qq空間就是大量采用這種方式來實作跨域資料交換的)。JSONP是一種腳本注入(Script Injection)行為,是以有一定的安全隐患。

跨域請求之jQuery的ajax jsonp的使用解惑

     前天在項目中寫的一個ajax jsonp的使用,出現了問題:可以成功獲得請求結果,但沒有執行success方法,直接執行了error方法提示錯誤——ajax jsonp之前并沒有用過,對其的了解為跟普通的ajax請求差不多,沒有深入了解;出現了這種錯誤,幾經調試(檢查背景的代碼和js部分的屬性設定)還是不行,讓我感覺很是意外和不解。于是,決定仔細研究下ajax jsonp的使用,并将最後測試成功的學習經驗和大家分享下!

  首先,貼出可以成功執行的代碼:

      (頁面部分)

jsonp跨域請求之jQuery的ajax jsonp的使用解惑
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 2 <html xmlns="http://www.w3.org/1999/xhtml" >
 3 <head>
 4     <title>Untitled Page</title>
 5      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
 6      <script type="text/javascript">
 7     jQuery(document).ready(function(){
 8         $.ajax({
 9             type : "get",
10             async:false,
11             url : "ajax.ashx",
12             dataType : "jsonp",
13             jsonp: "callbackparam",//傳遞給請求處理程式或頁面的,用以獲得jsonp回調函數名的參數名(預設為:callback)
14             jsonpCallback:"success_jsonpCallback",//自定義的jsonp回調函數名稱,預設為jQuery自動生成的随機函數名
15             success : function(json){
16                 alert(json);
17                 alert(json[0].name);
18             },
19             error:function(){
20                 alert('fail');
21             }
22         });
23         var a="firstName Brett";
24         alert(a);
25     });
26     </script>
27     </head>
28  <body>
29  </body>
30 </html>      
jsonp跨域請求之jQuery的ajax jsonp的使用解惑

(處理程式部分)

jsonp跨域請求之jQuery的ajax jsonp的使用解惑
1 <%@ WebHandler Language="C#" Class="ajax" %>
 2 
 3 using System;
 4 using System.Web;
 5 
 6 public class ajax : IHttpHandler {
 7     
 8     public void ProcessRequest (HttpContext context) {
 9         context.Response.ContentType = "text/plain";
10         string callbackFunName = context.Request["callbackparam"];
11         context.Response.Write(callbackFunName + "([ { name:\"John\"} ] )");
12     }
13  
14     public bool IsReusable {
15         get {
16             return false;
17         }
18     }
19 
20 }      
jsonp跨域請求之jQuery的ajax jsonp的使用解惑

  (請求抓包截圖)

jsonp跨域請求之jQuery的ajax jsonp的使用解惑

ajax請求參數說明:

dataType  String

預期伺服器傳回的資料類型。如果不指定,jQuery 将自動根據 HTTP 包 MIME 資訊來智能判斷,比如XML MIME類型就被識别為XML。在1.4中,JSON就會生成一個JavaScript對象,而script則會執行這個腳本。随後伺服器端傳回的資料會根據這個值解析後,傳遞給回調函數。可用值:

"xml": 傳回 XML 文檔,可用 jQuery 處理。

"html": 傳回純文字 HTML 資訊;包含的script标簽會在插入dom時執行。

"script": 傳回純文字 JavaScript 代碼。不會自動緩存結果。除非設定了"cache"參數。'''注意:'''在遠端請求時(不在同一個域下),所有POST請求都将轉為GET請求。(因為将使用DOM的script标簽來加載)

"json": 傳回 JSON 資料 。

"jsonp": JSONP 格式。使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 将自動替換 ? 為正确的函數名,以執行回調函數。

"text": 傳回純文字字元串

jsonp   String

在一個jsonp請求中重寫回調函數的名字。這個值用來替代在"callback=?"這種GET或POST請求中URL參數裡的"callback"部分,比如{jsonp:'onJsonPLoad'}會導緻将"onJsonPLoad=?"傳給伺服器。

jsonpCallback   String

為jsonp請求指定一個回調函數名。這個值将用來取代jQuery自動生成的随機函數名。這主要用來讓jQuery生成度獨特的函數名,這樣管理請求更容易,也能友善地提供回調函數和錯誤處理。你也可以在想讓浏覽器緩存GET請求的時候,指定這個回調函數名。

   ajax jsonp與普通的ajax請求的主要差別在于——請求響應結果的處理。如上面代碼所示的響應結果為:

success_jsonpCallback([ { name:"John"} ] ); ————其實就是,調用jsonp回調函數success_jsonpCallback,并将要響應的字元串或json傳入此方法(作為參數值),其底層的實作,大概的猜想應該是:
           
function success_jsonpCallback(data)
        {
            success(data);
        }
           
經測試,ajax jsonp對同步或異步請求沒有影響。
           
好了,如有解釋不對或不完整的地方,希望大家見諒,歡迎留言、扔闆磚!