http://blog.csdn.net/huaishuming/article/details/40046729javascript
說明:html
在作2個系統間傳值時出現:前端
根據以往經驗我想是跨域問題出現了。java
哎看了看果不其然:jquery
個人代碼以下:
web
前言ajax
因爲Sencha Touch 2這種開發模式的特性,基本決定了它原生的數據交互行爲幾乎只能經過AJAX來實現。數據庫
固然了,經過調用強大的PhoneGap插件而後打包,你能夠實現100%的Socket通信和本地數據庫功能,又或者經過HTML5的 WebSocket也能夠實現與服務器的通信和服務端推功能,但這兩種方式都有其侷限性,前者須要PhoneGap支持,後者要求用戶設備必須支持 WebSocket,所以都不能算是ST2的原生解決方案,原生的只有AJAX。json
說到AJAX就會不可避免的面臨兩個問題,第一個是AJAX以何種格式來交換數據?第二個是跨域的需求如何解決?這兩個問題目前都有不一樣的解決方案,好比數據能夠用自定義字符串或者用XML來描述,跨域能夠經過服務器端代理來解決。後端
但到目前爲止最被推崇或者說首選的方案仍是用JSON來傳數據,靠JSONP來跨域。而這就是本文將要講述的內容。
JSON(JavaScript Object Notation)和JSONP(JSON with Padding)雖然只有一個字母的差異,但其實他們根本不是一回事兒:JSON是一種數據交換格式,而JSONP是一種依靠開發人員的聰明才智創造出的 一種非官方跨域數據交互協議。咱們拿最近比較火的諜戰片來打個比方,JSON是地下黨們用來書寫和交換情報的「暗號」,而JSONP則是把用暗號書寫的情 報傳遞給本身同志時使用的接頭方式。看到沒?一個是描述信息的格式,一個是信息傳遞雙方約定的方法。
既然隨便聊聊,那咱們就再也不採用教條的方式來說述,而是把關注重心放在幫助開發人員理解是否應當選擇使用以及如何使用上。
什麼是JSON
前面簡單說了一下,JSON是一種基於文本的數據交換方式,或者叫作數據描述格式,你是否該選用他首先確定要關注它所擁有的優勢。
JSON的優勢:
一、基於純文本,跨平臺傳遞極其簡單;
二、Javascript原生支持,後臺語言幾乎所有支持;
三、輕量級數據格式,佔用字符數量極少,特別適合互聯網傳遞;
四、可讀性較強,雖然比不上XML那麼一目瞭然,但在合理的依次縮進以後仍是很容易識別的;
五、容易編寫和解析,固然前提是你要知道數據結構;
JSON的缺點固然也有,但在做者看來實在是可有可無的東西,因此再也不單獨說明。
JSON的格式或者叫規則:
JSON可以以很是簡單的方式來描述數據結構,XML能作的它都能作,所以在跨平臺方面二者徹底不分伯仲。
一、JSON只有兩種數據類型描述符,大括號{}和方括號[],其他英文冒號:是映射符,英文逗號,是分隔符,英文雙引號""是定義符。
二、大括號{}用來描述一組「不一樣類型的無序鍵值對集合」(每一個鍵值對能夠理解爲OOP的屬性描述),方括號[]用來描述一組「相同類型的有序數據集合」(可對應OOP的數組)。
三、上述兩種集合中如有多個子項,則經過英文逗號,進行分隔。
四、鍵值對以英文冒號:進行分隔,而且建議鍵名都加上英文雙引號」",以便於不一樣語言的解析。
五、JSON內部經常使用數據類型無非就是字符串、數字、布爾、日期、null 這麼幾個,字符串必須用雙引號引發來,其他的都不用,日期類型比較特殊,這裏就不展開講述了,只是建議若是客戶端沒有按日期排序功能需求的話,那麼把日期 時間直接做爲字符串傳遞就好,能夠省去不少麻煩。
JSON實例:
// 描述一我的 var person = { "Name": "Bob", "Age": 32, "Company": "IBM", "Engineer": true } // 獲取這我的的信息 var personAge = person.Age; // 描述幾我的 var members = [ { "Name": "Bob", "Age": 32, "Company": "IBM", "Engineer": true }, { "Name": "John", "Age": 20, "Company": "Oracle", "Engineer": false }, { "Name": "Henry", "Age": 45, "Company": "Microsoft", "Engineer": false } ] // 讀取其中John的公司名稱 var johnsCompany = members[1].Company; // 描述一次會議 var conference = { "Conference": "Future Marketing", "Date": "2012-6-1", "Address": "Beijing", "Members": [ { "Name": "Bob", "Age": 32, "Company": "IBM", "Engineer": true }, { "Name": "John", "Age": 20, "Company": "Oracle", "Engineer": false }, { "Name": "Henry", "Age": 45, "Company": "Microsoft", "Engineer": false } ] } // 讀取參會者Henry是否工程師 var henryIsAnEngineer = conference.Members[2].Engineer;
關於JSON,就說這麼多,更多細節請在開發過程當中查閱資料深刻學習。
什麼是JSONP
先說說JSONP是怎麼產生的:
其實網上關於JSONP的講解有不少,但卻千篇一概,並且雲裏霧裏,對於不少剛接觸的人來說理解起來有些困難,小可不才,試着用本身的方式來闡釋一下這個問題,看看是否有幫助。
一、一個衆所周知的問題,Ajax直接請求普通文件存在跨域無權限訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一概不許;
二、不過咱們又發現,Web頁面上調用js文件時則不受是否跨域的影響(不只如此,咱們還發現凡是擁有」src」這個屬性的標籤都擁有跨域的能力,好比<script>、<img>、<iframe>);
三、因而能夠判斷,當前階段若是想經過純web端(ActiveX控件、服務端代理、屬於將來的HTML5之Websocket等方式不算)跨域訪問數據就只有一種可能,那就是在遠程服務器上設法把數據裝進js格式的文件裏,供客戶端調用和進一步處理;
四、恰巧咱們已經知道有一種叫作JSON的純字符數據格式能夠簡潔的描述複雜數據,更妙的是JSON還被js原生支持,因此在客戶端幾乎能夠爲所欲爲的處理這種格式的數據;
五、這樣子解決方案就呼之欲出了,web客戶端經過與調用腳本如出一轍的方式,來調用跨域服務器上動態生成的js格式文件(通常以JSON爲後綴),顯而易見,服務器之因此要動態生成JSON文件,目的就在於把客戶端須要的數據裝入進去。
六、客戶端在對JSON文件調用成功以後,也就得到了本身所需的數據,剩下的就是按照本身需求進行處理和展示了,這種獲取遠程數據的方式看起來很是像AJAX,但其實並不同。
七、爲了便於客戶端使用數據,逐漸造成了一種非正式傳輸協議,人們把它稱做JSONP,該協議的一個要點就是容許用戶傳遞一個callback 參數給服務端,而後服務端返回數據時會將這個callback參數做爲函數名來包裹住JSON數據,這樣客戶端就能夠隨意定製本身的函數來自動處理返回數 據了。
若是對於callback參數如何使用還有些模糊的話,咱們後面會有具體的實例來說解。
JSONP的客戶端具體實現:
無論jQuery也好,ExtJs也罷,又或者是其餘支持jsonp的框架,他們幕後所作的工做都是同樣的,下面我來按部就班的說明一下jsonp在客戶端的實現:
一、咱們知道,哪怕跨域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>
毫無疑問,頁面將會彈出一個提示窗體,顯示跨域調用成功。
二、如今咱們在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"> localHandler function'' 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的服務者都要面對不少服務對象,而 這些服務對象各自的本地函數都不相同啊?咱們接着往下看。
三、聰明的開發者很容易想到,只要服務端提供的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"> 獲得航班信息查詢結果後的回調函數 flightHandler function'' data.price '' '' data.tickets ''); }; 提供jsonp服務的url地址(無論是什麼類型的地址,最終生成的返回值都是一段javascript代碼) url ""; 建立script標籤,設置其屬性 script document.createElement(script); script.setAttribute(src, url); 把script標籤加入head,此時調用開始 ''0].appendChild(script); </script> </head> <body> </body> </html>
此次的代碼變化比較大,再也不直接把遠程js文件寫死,而是編碼實現動態查詢,而這也正是jsonp客戶端實現的核心部分,本例中的重點也就在於如何完成jsonp調用的全過程。
咱們看到調用的url中傳遞了一個code參數,告訴服務器我要查的是CA1998次航班的信息,而callback參數則告訴服務器,個人本地回調函數叫作flightHandler,因此請把查詢結果傳入這個函數中進行調用。
OK,服務器很聰明,這個叫作flightResult.aspx的頁面生成了一段這樣的代碼提供給jsonp.html(服務端的實現這裏就不演示了,與你選用的語言無關,說到底就是拼接字符串):
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
咱們看到,傳遞給flightHandler函數的是一個json,它描述了航班的基本信息。運行一下頁面,成功彈出提示窗口,jsonp的執行全過程順利完成!
四、到這裏爲止的話,相信你已經可以理解jsonp的客戶端實現原理了吧?剩下的就是如何把代碼封裝一下,以便於與用戶界面交互,從而實現屢次和重複調用。
什麼?你用的是jQuery,想知道jQuery如何實現jsonp調用?好吧,那我就好人作到底,再給你一段jQuery使用jsonp的代碼(咱們依然沿用上面那個航班信息查詢的例子,假定返回jsonp結果不變):
<!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">function""false""""""// jsonpCallback:flightHandler,自定義的jsonp回調函數名稱,默認爲jQuery自動生成的隨機函數名,也能夠寫"?",jQuery會自動爲你處理數據 function'' json.price '' json.tickets ''); }, error: (){ alert(fail); } }); }); </script> </head> <body> </body> </html>
是否是有點奇怪?爲何我此次沒有寫flightHandler這個函數呢?並且居然也運行成功了!哈哈,這就是jQuery的功勞 了,jquery在處理jsonp類型的ajax時(仍是忍不住吐槽,雖然jquery也把jsonp納入了ajax,但其實它們真的不是一回事兒),自 動幫你生成回調函數並把數據取出來供success屬性方法來調用,是否是很爽呀?
好啦,寫到這裏,我已經無力再寫下去,又困又累,得趕忙睡覺。朋友們要是看這不錯,以爲有啓發,給點個「推薦」唄!因爲實在比較簡單,因此就再也不提供demo源碼下載了。
沒想到上了博客園的頭條推薦。看到你們對這篇文章的承認和評論,仍是很開心的,這裏針對ajax與jsonp的異同再作一些補充說明:
4月20日下午補充
一、ajax和jsonp這兩種技術在調用方式上「看起來」很像,目的也同樣,都是請求一個url,而後把服務器返回的數據進行處理,所以jquery和ext等框架都把jsonp做爲ajax的一種形式進行了封裝;
二、但ajax和jsonp其實本質上是不一樣的東西。ajax的核心是經過XmlHttpRequest獲取非本頁內容,而jsonp的核心則是動態添加<script>標籤來調用服務器提供的js腳本。
三、因此說,其實ajax與jsonp的區別不在因而否跨域,ajax經過服務端代理同樣能夠實現跨域,jsonp自己也不排斥同域的數據的獲取。
四、還有就是,jsonp是一種方式或者說非強制性協議,如同ajax同樣,它也不必定非要用json格式來傳遞數據,若是你願意,字符串都行,只不過這樣不利於用jsonp提供公開服務。
總而言之,jsonp不是ajax的一個特例,哪怕jquery等巨頭把jsonp封裝進了ajax,也不能改變這一點!
http://www.cnblogs.com/JerryTian/p/4194900.html
好久沒有寫隨筆了,老是感受沒時間,其實時間就是。。。廢話少說,前幾天,工做上有一新需求,須要前端web頁面異步調用後臺的Webservice方法 返回信息。實現方法有多種,本例採用jQuery+Ajax,完成後,在本地調試了一切ok,可是部署到服務器上之後就出現問題了,後臺服務調用沒有響 應,怎麼回事?代碼沒怎麼改動,惟一修改的地方就是jQuery的ajax方法中的url地址。難道是這裏的問題,通過檢查和調試,發現原來是同源策略在 做怪,咱們知道,JavaScript或jQuery是在Web前端開發中常用的動態腳本技術。在JavaScript中,有一個很重要的安全性限 制,被稱爲「Same- Origin Policy」(同源策略)。這一策略對於JavaScript代碼可以訪問的頁面內容作了很重要的限制,即JavaScript只能訪問與包含它的文檔 或腳本 在同一域名下的內容。不一樣域名下的腳本不能互相訪問,即使是子域也不行。關於同源策略,讀者可百度更詳細的解釋,這裏再也不贅述。
可是有時候又不可避免地須要進行跨域操做,這時候「同源策略」就是一個限制了,怎麼辦呢?採用JSONP跨域GET請求是一個經常使用的解決方案,下面咱們來看一下JSONP跨域是如何實現的,並探討下JSONP跨域的原理。
這裏提到了JSONP,那有人就問了,它同JSON有什麼區別不一樣和區別呢,接下咱們就來看看,百度百科有如下說明:
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function CallWebServiceByJsonp() {
$(
"#SubEquipmentDetails"
).html(
''
);
$.ajax({
type:
"GET"
,
cache:
false
,
url:
"http://servername/webservice/webservice.asmx/GetSingleInfo"
,
data: { strCparent: $(
"#Equipment_ID"
).val() },
dataType:
"jsonp"
,
//jsonp: "callback",
jsonpCallback:
"OnGetMemberSuccessByjsonp"
});
}
function OnGetMemberSuccessByjsonp(data) {
//處理data
alert(data);
}
|
後端的WebService代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet =
true
)]
public
void
GetSingleInfo(
string
strCparent)
{
string
ret =
string
.Empty;
HttpContext.Current.Response.ContentType =
"application/json;charset=utf-8"
;
string
jsonCallBackFunName = HttpContext.Current.Request.Params[
"callback"
].ToString();
//string jsonCallBackFunName1 = HttpContext.Current.Request.QueryString["callback"].Trim();
//上面代碼必須
//中間代碼執行本身的業務操做,可返回本身的任意信息(多數據類型)
BLL.equipment eq_bll =
new
BLL.equipment();
List<Model.equipment> equipmentList =
new
List<Model.equipment>();
equipmentList = eq_bll.GetModelEquimentList(strCparent);
ret = JsonConvert.SerializeObject(equipmentList);
//下面代碼必須
HttpContext.Current.Response.Write(
string
.Format(
"{0}({1})"
, jsonCallBackFunName, ret));
HttpContext.Current.Response.End();
}
|
如上所示,前端的CallWebServiceByJsonp方法採用jQuery的ajax方法調用後端的Web服務GetSingleInfo 方法,後臺的GetSingleInfo方法,使用前端的回調方法OnGetMemberSuccessByjsonp包裝後臺的業務操做的JSON對 象,返回給前端一段javascript片斷執行。巧妙的解決了跨域訪問問題。
JSONP的缺點:
JSONP不提供錯誤處理。若是動態插入的代碼正常運行,你能夠獲得返回,可是若是失敗了,那麼什麼都不會發生。