首頁 >web前端 >js教程 >js跨域請求的5中解決方式_javascript技巧

js跨域請求的5中解決方式_javascript技巧

WBOY
WBOY原創
2016-05-16 15:52:001178瀏覽

跨域請求資料解決方案主要有以下解決方法:

JSONP方式
表单POST方式
服务器代理
Html5的XDomainRequest
Flash request

分開說明:

一、JSONP:

直觀的理解:

就是在客戶端動態註冊一個函數

function a(data),然後將函數名稱傳到伺服器,伺服器傳回一個a({/*json*/})到客戶端運作,這樣就呼叫客戶端的

function a(data),從而實現了跨域.

誕生背景:

1、Ajax直接請求普通文件存在跨域無權訪問的問題,甭管是靜態頁面、動態網頁、web服務、wcf、只要是跨域請求,一律不行。

2、不過,web頁面上呼叫js檔案時則不受此影響

3.進一步推廣,我們發現,凡是擁有Src屬性的標籤都有跨域能力,如:<script><img alt="js跨域請求的5中解決方式_javascript技巧" ><iframe></script>

4、於是,目前如果想透過純web端(ActiveX控制項、服務端代理程式、屬於未來的HTML5之Websocket等方式不算)跨網域存取數據,就只能使用以下方式:就是在遠端伺服器上設法把資料裝進js格式的文字裡,供客戶端呼叫和進一步處理。

5、JSON就是一種純字元資料格式,且能唄js原生支援。

6、這樣解決方案出爐:web客戶端透過與呼叫腳本一模一樣的方式,來呼叫跨域伺服器上動態產生的js格式檔案(一般以json為後綴)。

7.客戶端在對json檔案呼叫成功後,也就得到了所需數據,剩下的就是按照自己的需求進行處理了。

8為了方便客戶端使用數據,逐漸形成了一種非正式的傳輸協議,稱為jsonp。協定的一個重點是允許使用者傳遞一個callback參數給伺服器,然後伺服器返回資料時會將這個callback參數作為函數名稱來包裹住json數據,這樣客戶端就可以隨意自訂自己的函數來處理傳回資料了。

具體實作:

不管jQuery也好,extjs也罷,又或者是其他支援jsonp的框架,他們幕後所做的工作都是一樣的,下面我來循序漸進的說明一下jsonp在客戶端的實現:

1、我們知道,就算跨域js檔案中的程式碼(當然指符合web腳本安全策略的),web頁面也是可以無條件執行的。

遠端伺服器remoteserver.com根目錄下有個remote.js檔案程式碼如下:

alert('我是遠端檔案');

本地伺服器localserver.com下方有個jsonp.html頁面程式碼如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>

</body>
</html>

毫無疑問,頁面將會彈出一個提示窗體,顯示跨域呼叫成功。

2、現在我們在jsonp.html頁面定義一個函數,然後在遠端remote.js中傳入資料進行呼叫。

jsonp.html頁面代碼如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <script type="text/javascript">
  var localHandler = function(data){
    alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
  };
  </script>
  <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>

</body>
</html>

remote.js檔案程式碼如下:

localHandler({"result":"我是遠端js帶來的資料"});
運行之後查看結果,頁面成功彈出提示窗口,顯示本地函數被跨域的遠端js呼叫成功,並且還接收了遠端js帶來的資料。很欣喜,跨域遠端取得資料的目的基本上實作了,但是又一個問題出現了,我要怎麼讓遠端js知道它應該呼叫的本地函數叫什麼名字呢?畢竟是jsonp的服務者都要面對許多服務對象,而這些服務對象各自的本地函數都不相同啊?我們接著往下看。

3、聰明的開發者很容易想到,只要服務端提供的js腳本是動態產生的就行了唄,這樣呼叫者可以傳一個參數過去告訴服務端「我想要一段呼叫XXX函數的js程式碼,請你回傳給我”,於是伺服器就可以按照客戶端的需求來產生js腳本並回應了。

看jsonp.html頁面的程式碼:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <script type="text/javascript">
  // 得到航班信息查询结果后的回调函数
  var flightHandler = function(data){
    alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
  };
  // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
  var url = "http://flightQuery.com/jsonp/flightResult.aspx&#63;code=CA1998&callback=flightHandler";
  // 创建script标签,设置其属性
  var script = document.createElement('script');
  script.setAttribute('src', url);
  // 把script标签加入head,此时调用开始
  document.getElementsByTagName('head')[0].appendChild(script); 
  </script>
</head>
<body>

</body>
</html>

這次的程式碼變化比較大,不再直接把遠端js檔案寫死,而是編碼實作動態查詢,而這也正是jsonp客戶端實現的核心部分,本例中的重點也就在於如何完成jsonp調用的全過程。

我們看到調用的url中傳遞了一個code參數,告訴伺服器我要查的是CA1998次航班的信息,而callback參數則告訴伺服器,我的本地回調函數叫做flightHandler,所以請把查詢結果傳入這個函數中進行呼叫。

flightHandler({
  "code": "CA1998",
  "price": 1780,
  "tickets": 5
});

我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!

4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。

什么?你用的是jQuery,想知道jQuery如何实现jsonp调用?好吧,那我就好人做到底,再给你一段jQuery使用jsonp的代码(我们依然沿用上面那个航班信息查询的例子,假定返回jsonp结果不变):

OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" >
 <head>
   <title>Untitled Page</title>
   <script type="text/javascript" src=jquery.min.js"></script>
   <script type="text/javascript">
   jQuery(document).ready(function(){ 
    $.ajax({
       type: "get",
       async: false,
       url: "http://flightQuery.com/jsonp/flightResult.aspx&#63;code=CA1998",
       dataType: "jsonp",
       jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
       jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"&#63;",jQuery会自动为你处理数据
       success: function(json){
         alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
       },
       error: function(){
         alert('fail');
       }
     });
   });
   </script>
   </head>
 <body>
 </body>
 </html>

是不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时(还是忍不住吐槽,虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用,是不是很爽呀?

以上所述就是本文的全部内容了,希望大家能够喜欢。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn