第113天:Ajax跨域請求解決方法

半指溫柔樂發表於2017-12-13

一、原生JS實現ajax

第一步獲得XMLHttpRequest物件

第二步:設定狀態監聽函式

第三步:open一個連線,true是非同步請求

第四部:send一個請求,可以傳送一個物件和字串,不需要傳遞資料傳送null

第五步:在監聽函式中,判斷readyState=4&&status=200表示請求成功

第六步:使用responseTextresponseXML接受響應資料,並使用原生JS操作DOM進行顯示

 1 var ajax = new XMLHttpRequest();
 2 ajax.onreadystatechange = function(){
 3     console.log(ajax.readyState);
 4     console.log(ajax.status);
 5     if(ajax.readyState==4 && ajax.status==200){
 6         console.log(ajax.responseText);
 7         console.log(ajax.responseXML);//返回不是XML,顯示null
 8         console.log(JSON.parse(ajax.responseText));
 9         console.log(eval("("+ajax.responseText+")"));
10         }
11 }
12 ajax.open("GET","h51701.json",true);
13 ajax.send(null);

二、ajax的跨域請求

[跨域請求處理]由於在JS中存在同源策略。當請求不同協議名,不同埠號,不同主機名下面的檔案時,將會違背同源策略,無法請求成功!需要進行跨域處理! 

 1、後臺PHP進行設定: 

前臺無需任何設定,在後臺被請求的PHP檔案中,寫入一條header

header("Access-Control-Allow-Origin:*");//表示允許哪些域名請求這個PHP檔案,*表示所有域名都允許

2、使用src屬性+JSONP實現跨域

 ① 擁有src屬性的標籤自帶跨域功能!所以可以使用script標籤的src屬性請求後臺資料

 1 <script src=”http://127.0.0.1/json.php” type=”text/javascript” charset=”utf-8″></ script> 

 ② 由於src在載入資料成功後,後直接將載入內容放入到script標籤中

 所以,後臺直接返回JSON字串將不能在script標籤中解析
 因此,後臺應該返回給前臺一個回到函式名,並將JSON字串作為引數傳入

 後臺PHP檔案中返回:

echo "callBack({$str})";

③ 前臺接收到返回的回到函式,將直接在script標籤中呼叫。因此需要宣告這樣一個回撥函式,作為請求成功的回撥。

function callBack(data){
       alert("請求成功");
       console.log(data);
  }

3、JQuery的ajax實現JSONP

 ① 在ajax請求時,設定dataType為”json
 ② 後臺返回時,依然需要返回回撥函式。但是,ajax在傳送請求時會預設使用get請求將回到函式名發給後臺,後臺可以使用$_GET[`callback`]取出回撥函式名:

 echo "{$_GET[`callback`]}({$str})";

③ 後臺返回以後,ajax依然可以用success作為成功的回撥函式:

success:function(data){}

當然後臺也可以隨便返回一個回撥函式名。

echo "callBack({$str})";

前臺只要請求成功,就會自動呼叫這個函式。類似於第2條的② ③步

三、jsonp解決Ajax跨域請求問題

1、json和jsonp的區別

  JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它基於JavaScript(Standard ECMA-262 3rd Edition – December 1999)的一個子集。 JSON採用完全獨立於語言的文字格式,但是也使用了類似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的資料交換語言。易於人閱讀和編寫,同時也易於機器解析和生成(網路傳輸速度快)。

  JSONP(JSON with Padding)是JSON的 一種“使用模式”,可用於解決主流瀏覽器的跨域資料訪問的問題。由於同源策略,一般來說位於 server1.example.com 的網頁無法與不是 server1.example.com的伺服器溝通,而 HTML 的<script> 元素是一個例外。利用 <script> 元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並不是 JSON,而是任意的JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。

   到這裡,應該明白了,JSON是一種輕量級的資料交換格式,像xml一樣,是用來描述資料間的。JSONP是一種使用JSON資料的方式,返回的不是JSON物件,是包含JSON物件的javaScript指令碼

       那JSONP是如何工作的呢,我們知道,由於同源策略的限制,XmlHttpRequest只允許請求當前源(域名、協議、埠)的資源。若要跨域請求出於安全性考慮是不行的,但是我們發現,Web頁面上呼叫js檔案時則不受是否跨域的影響,而且擁有”src”這個屬性的標籤都擁有跨域的能力,比如<script><img>、<iframe>,這時候,聰明的程式猿就想到了變通的方法,如果要進行跨域請求, 通過使用html的script標記來進行跨域請求,並在響應中返回要執行的script程式碼,其中可以直接使用JSON傳遞 javascript物件。即在跨域的服務端生成JSON資料,然後包裝成script指令碼回傳,著不就突破同源策略的限制,解決了跨域訪問的問題了麼。

下面我們就看下怎麼實現:

前端程式碼:

 1 function CallWebServiceByJsonp() {
 2         $("#SubEquipmentDetails").html(``);
 3         $.ajax({
 4             type: "GET",
 5             cache: false,
 6             url: "http://servername/webservice/webservice.asmx/GetSingleInfo",
 7             data: { strCparent: $("#Equipment_ID").val() },
 8             dataType: "jsonp",
 9             //jsonp: "callback",
10             jsonpCallback: "OnGetMemberSuccessByjsonp"
11         });
12 }
13  
14 function OnGetMemberSuccessByjsonp(data) {
15     //處理data
16     alert(data);
17 }

後端的WebService程式碼:

 1 [WebMethod]
 2 [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
 3 public void GetSingleInfo(string strCparent)
 4 {
 5     string ret = string.Empty;
 6     HttpContext.Current.Response.ContentType = "application/json;charset=utf-8";
 7     string jsonCallBackFunName = HttpContext.Current.Request.Params["callback"].ToString();
 8     //string jsonCallBackFunName1 = HttpContext.Current.Request.QueryString["callback"].Trim();
 9      
10     //上面程式碼必須
11     //中間程式碼執行自己的業務操作,可返回自己的任意資訊(多資料型別)
12  
13     BLL.equipment eq_bll = new BLL.equipment();
14     List<Model.equipment> equipmentList = new List<Model.equipment>();
15     equipmentList = eq_bll.GetModelEquimentList(strCparent);
16     ret = JsonConvert.SerializeObject(equipmentList);
17  
18     //下面程式碼必須
19     HttpContext.Current.Response.Write(string.Format("{0}({1})", jsonCallBackFunName, ret));
20     HttpContext.Current.Response.End();
21 }

如上所示,前端的CallWebServiceByJsonp方法採用jQueryajax方法呼叫後端的Web服務GetSingleInfo方法,後臺的GetSingleInfo方法,使用前端的回撥方法OnGetMemberSuccessByjsonp包裝後臺的業務操作的JSON物件,返回給前端一段javascript片段執行。巧妙的解決了跨域訪問問題。

     JSONP的缺點:

  JSONP不提供錯誤處理。如果動態插入的程式碼正常執行,你可以得到返回,但是如果失敗了,那麼什麼都不會發生。


相關文章