最近做一個項目需要在客戶端去第三方供應商服務器獲取數據,第一想到的方法就是通過ajax的方式發送請求獲取數據。由於我們的系統和第三方系統不在一個域,因此通過ajax發送請求就碰到了跨域的問題。
在網上查找了一些方法,發現一般解決跨域問題就是兩種方式:一是通過ajax在服務端通過代理的方式實現;二是通過jsonp的方式。
經過兩種方式比較,最終選擇了第二種方式實現了跨域請求。下面結合本次需求的經歷簡單總結一下JSONP的方式。
我們都知道ajax直接請求普通文件都存在跨域無權限訪問的問題,但是Web頁面上調用JS文件不受是否跨域的影響,於是就可以想象到,如果在遠程服務器端設法將數據裝進JS格式的文件里,那么客戶端就可以獲取到,並不受跨域的影響。這就是JSONP基本的實現原理。
下面舉例說明:
1、本地有一個html文件a.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('我是本地函數,可以被跨域的b.js文件調用,遠程js帶來的數據是:' + data.result); }; </script> <script type="text/javascript" src="http://test.com/b.js"></script> </head> <body> </body> </html>
2、遠程服務器test.com根目錄有一個b.js文件
localHandler({"result":"跨域測試"})
運行本地的html文件,發現成功彈出提示框,並且成功接收到服務器test.com帶來的js數據。
以上就是一個基本的JSOP跨域請求的例子。
但是在實際開發過程中JSONP的服務者面對很多的服務對象,每個服務對象各自本地的函數都不相同,那么他們是怎么調用的呢?
解決方式很簡單,就是在客戶端請求服務器時,在url中傳一個callback參數,callback參數傳遞的是本地客戶端需要回調的函數名稱。服務端根據這個callback參數動態生生成js腳本供客戶端進行調用。
例如,請求http:test.com/c.aspx?callback=funCallBack這樣一個服務地址,c.aspx頁面根據callback參數內容,向客戶端返回以下js字符串
funCallBack({"result":"******"})
這樣客戶端就能順利調用funCallBack函數。
JSONP基本原理就是這樣,其實很簡單。我們日常使用的js框架,像jQuery,就在ajax中對JSONP進行了非常好的封裝,
們這次就是結合jQuery和JSONP解決的跨域問題。(ajax和jsonp兩種技術在調用方式相似,都是通過請求url,然后對服務器返回的數據進行處理,因此jquery和ext等很多框架都喜歡把jsonp座位ajax的形式進行封裝。實際他們本質還是有區別的,ajax核心是通過XmlHttpRequest獲取內容,而jsonp核心是通過動態添加<script>標簽來調用服務器提供的js腳本)
1、客戶端代碼如下
<!DOCTYPE html> <html> <head> <title></title> <script type="text/javascript" src="js/jquery-2.1.4.js"></script> <script type="text/javascript"> function doTest(){ $.ajax({ type:"Get", url :"test1.php?user=admin&password=123", dataType:"jsonp", jsonp:"callback",//傳遞給請求服務器處理程序或頁面的,用以獲得JSONP回調函數名 jsonpCallback:"jsonCallBackTest",//自定義的jsonp回調函數名稱,默認為jQuery自動生成的隨機函數名,此屬性可不配置 success:function(data){ alert(data.user+" "+data.password); }, error:function(){ alert("error"); } }); } function jsonCallBackTest(data){ alert("jsoncallback"+data.user+" "+data.password); } </script> </head> <body> <button onclick="doTest()">button</button> </body> </html>
2、服務器代碼
<?php /** * Created by PhpStorm. * User: zhoufy * Date: 15/11/26 * Time: 21:22 */ header('Content-Type:text/html;Charset=utf-8'); $arr = array( "user"=>$_GET["user"], "password"=>$_GET["password"] ); echo $_GET['callback']."(".json_encode($arr).")";//此處的callback需要和客戶端ajax請求中的jsonp屬性保持一致。
運行test1.html,發現成功執行了jsonCallBackTest方法,然后又執行了success屬性方法。
執行jsonCallBackTest方法可以理解,是因為在jquery的ajax訪問中設置了jsonpCallback屬性,因此會觸發對應的回調函數。
那么怎么success屬性方法也會被執行呢?其實這是jquery的封裝,jquery在處理jsonp類型的ajax時,自動生成回調函數並把數據取出來供success屬性方法調用。
好了,寫到這里相信大家對jquery的jsonp處理跨域請求有了一定了解吧!第一次在博客園寫博客,希望看到的朋友多多提意見和問題,謝謝!