RAP-Jsonp

?摘自:http://www.qdfuns.com/notes/16738/1b6ad6125747d28592a53a960b44c6f4.html

什么是JSONP?

先說(shuō)說(shuō)JSONP是怎么產(chǎn)生的:

其實(shí)網(wǎng)上關(guān)于JSONP的講解有很多,但卻千篇一律,而且云里霧里,對(duì)于很多剛接觸的人來(lái)講理解起來(lái)有些困難,著用自己的方式來(lái)闡釋一下這個(gè)問(wèn)題,看看是否有幫助。

1、一個(gè)眾所周知的問(wèn)題,Ajax直接請(qǐng)求普通文件存在跨域無(wú)權(quán)限訪問(wèn)的問(wèn)題,甭管你是靜態(tài)頁(yè)面、動(dòng)態(tài)網(wǎng)頁(yè)、web服務(wù)、WCF,只要是跨域請(qǐng)求,一律不準(zhǔn)。

2、不過(guò)我們又發(fā)現(xiàn),Web頁(yè)面上調(diào)用js文件時(shí)則不受是否跨域的影響(不僅如此,我們還發(fā)現(xiàn)凡是擁有"src"這個(gè)屬性的標(biāo)簽都擁有跨域的能力,比如、、)。

3、于是可以判斷,當(dāng)前階段如果想通過(guò)純web端(ActiveX控件、服務(wù)端代理、屬于未來(lái)的HTML5之Websocket等方式不算)跨域訪問(wèn)數(shù)據(jù)就只有一種可能,那就是在遠(yuǎn)程服務(wù)器上設(shè)法把數(shù)據(jù)裝進(jìn)js格式的文件里,供客戶端調(diào)用和進(jìn)一步處理。

4、恰巧我們已經(jīng)知道有一種叫做JSON的純字符數(shù)據(jù)格式可以簡(jiǎn)潔的描述復(fù)雜數(shù)據(jù),更妙的是JSON還被js原生支持,所以在客戶端幾乎可以隨心所欲的處理這種格式的數(shù)據(jù)。

5、這樣子解決方案就呼之欲出了,web客戶端通過(guò)與調(diào)用腳本一模一樣的方式,來(lái)調(diào)用跨域服務(wù)器上動(dòng)態(tài)生成的js格式文件(一般以JSON為后綴),顯而易見(jiàn),服務(wù)器之所以要?jiǎng)討B(tài)生成JSON文件,目的就在于把客戶端需要的數(shù)據(jù)裝入進(jìn)去。

6、客戶端在對(duì)JSON文件調(diào)用成功之后,也就獲得了自己所需的數(shù)據(jù),剩下的就是按照自己需求進(jìn)行處理和展現(xiàn)了,這種獲取遠(yuǎn)程數(shù)據(jù)的方式看起來(lái)非常像AJAX,但其實(shí)并不一樣。

7、為了便于客戶端使用數(shù)據(jù),逐漸形成了一種非正式傳輸協(xié)議,人們把它稱作JSONP,該協(xié)議的一個(gè)要點(diǎn)就是允許用戶傳遞一個(gè)callback參數(shù)給服務(wù)端,然后服務(wù)端返回?cái)?shù)據(jù)時(shí)會(huì)將這個(gè)callback參數(shù)作為函數(shù)名來(lái)包裹住JSON數(shù)據(jù),這樣客戶端就可以隨意定制自己的函數(shù)來(lái)自動(dòng)處理返回?cái)?shù)據(jù)了。

如果對(duì)于callback參數(shù)如何使用還有些模糊的話,我們后面會(huì)有具體的實(shí)例來(lái)講解。

JSONP的客戶端具體實(shí)現(xiàn):

不管jQuery也好,extjs也罷,又或者是其他支持jsonp的框架,他們幕后所做的工作都是一樣的,下面我來(lái)循序漸進(jìn)的說(shuō)明一下jsonp在客戶端的實(shí)現(xiàn):

1、我們知道,哪怕跨域js文件中的代碼(當(dāng)然指符合web腳本安全策略的),web頁(yè)面也是可以無(wú)條件執(zhí)行的。

遠(yuǎn)程服務(wù)器remoteserver.com根目錄下有個(gè)remote.js文件代碼如下:



本地服務(wù)器localserver.com下有個(gè)jsonp.html頁(yè)面代碼如下:



毫無(wú)疑問(wèn),頁(yè)面將會(huì)彈出一個(gè)提示窗體,顯示跨域調(diào)用成功。

2、現(xiàn)在我們?cè)趈sonp.html頁(yè)面定義一個(gè)函數(shù),然后在遠(yuǎn)程remote.js中傳入數(shù)據(jù)進(jìn)行調(diào)用。

jsonp.html頁(yè)面代碼如下:

remote.js文件代碼如下:





運(yùn)行之后查看結(jié)果,頁(yè)面成功彈出提示窗口,顯示本地函數(shù)被跨域的遠(yuǎn)程js調(diào)用成功,并且還接收到了遠(yuǎn)程js帶來(lái)的數(shù)據(jù)。

很欣喜,跨域遠(yuǎn)程獲取數(shù)據(jù)的目的基本實(shí)現(xiàn)了,但是又一個(gè)問(wèn)題出現(xiàn)了,我怎么讓遠(yuǎn)程js知道它應(yīng)該調(diào)用的本地函數(shù)叫什么名字呢?畢竟是jsonp的服務(wù)者都要面對(duì)很多服務(wù)對(duì)象,而這些服務(wù)對(duì)象各自的本地函數(shù)都不相同啊?我們接著往下看。

3、聰明的開(kāi)發(fā)者很容易想到,只要服務(wù)端提供的js腳本是動(dòng)態(tài)生成的就行了唄,這樣調(diào)用者可以傳一個(gè)參數(shù)過(guò)去告訴服務(wù)端 "我想要一段調(diào)用XXX函數(shù)的js代碼,請(qǐng)你返回給我",于是服務(wù)器就可以按照客戶端的需求來(lái)生成js腳本并響應(yīng)了。

看jsonp.html頁(yè)面的代碼:



這次的代碼變化比較大,不再直接把遠(yuǎn)程js文件寫(xiě)死,而是編碼實(shí)現(xiàn)動(dòng)態(tài)查詢,而這也正是jsonp客戶端實(shí)現(xiàn)的核心部分,本例中的重點(diǎn)也就在于如何完成jsonp調(diào)用的全過(guò)程。

我們看到調(diào)用的url中傳遞了一個(gè)code參數(shù),告訴服務(wù)器我要查的是CA1998次航班的信息,而callback參數(shù)則告訴服務(wù)器,我的本地回調(diào)函數(shù)叫做flightHandler,所以請(qǐng)把查詢結(jié)果傳入這個(gè)函數(shù)中進(jìn)行調(diào)用。

OK,服務(wù)器很聰明,這個(gè)叫做flightResult.aspx的頁(yè)面生成了一段這樣的代碼提供給jsonp.html

(服務(wù)端的實(shí)現(xiàn)這里就不演示了,與你選用的語(yǔ)言無(wú)關(guān),說(shuō)到底就是拼接字符串):



我們看到,傳遞給flightHandler函數(shù)的是一個(gè)json,它描述了航班的基本信息。運(yùn)行一下頁(yè)面,成功彈出提示窗口,jsonp的執(zhí)行全過(guò)程順利完成!

4、到這里為止的話,相信你已經(jīng)能夠理解jsonp的客戶端實(shí)現(xiàn)原理了吧?剩下的就是如何把代碼封裝一下,以便于與用戶界面交互,從而實(shí)現(xiàn)多次和重復(fù)調(diào)用。

jQuery如何實(shí)現(xiàn)jsonp調(diào)用?



是不是有點(diǎn)奇怪?為什么我這次沒(méi)有寫(xiě)flightHandler這個(gè)函數(shù)呢?而且竟然也運(yùn)行成功了!

這就是jQuery的功勞了,jquery在處理jsonp類型的ajax時(shí)(,雖然jquery也把jsonp歸入了ajax,但其實(shí)它們真的不是一回事兒),自動(dòng)幫你生成回調(diào)函數(shù)并把數(shù)據(jù)取出來(lái)供success屬性方法來(lái)調(diào)用,是不是很爽呀?

[attachimg][attachimg]

補(bǔ)充

這里針對(duì)ajax與jsonp的異同再做一些補(bǔ)充說(shuō)明:

1、ajax和jsonp這兩種技術(shù)在調(diào)用方式上"看起來(lái)"很像,目的也一樣,都是請(qǐng)求一個(gè)url,然后把服務(wù)器返回的數(shù)據(jù)進(jìn)行處理,因此jquery和ext等框架都把jsonp作為ajax的一種形式進(jìn)行了封裝。

2、但ajax和jsonp其實(shí)本質(zhì)上是不同的東西。ajax的核心是通過(guò)XmlHttpRequest獲取非本頁(yè)內(nèi)容,而jsonp的核心則是動(dòng)態(tài)添加標(biāo)簽來(lái)調(diào)用服務(wù)器提供的js腳本。

3、所以說(shuō),其實(shí)ajax與jsonp的區(qū)別不在于是否跨域,ajax通過(guò)服務(wù)端代理一樣可以實(shí)現(xiàn)跨域,jsonp本身也不排斥同域的數(shù)據(jù)的獲取。

4、還有就是,jsonp是一種方式或者說(shuō)非強(qiáng)制性協(xié)議,如同ajax一樣,它也不一定非要用json格式來(lái)傳遞數(shù)據(jù),如果你愿意,字符串都行,只不過(guò)這樣不利于用jsonp提供公開(kāi)服務(wù)。

總而言之,jsonp不是ajax的一個(gè)特例,哪怕jquery等巨頭把jsonp封裝進(jìn)了ajax,也不能改變這一點(diǎn)!


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 前言 說(shuō)到AJAX就會(huì)不可避免的面臨兩個(gè)問(wèn)題,第一個(gè)是AJAX以何種格式來(lái)交換數(shù)據(jù)?第二個(gè)是跨域的需求如何解決?這...
    蠟筆小噺沒(méi)有煩惱閱讀 1,618評(píng)論 4 43
  • 本文轉(zhuǎn)自,博客園,昵稱:[隨它去吧],http://www.cnblogs.com/dowinning/archi...
    戰(zhàn)神飄雪閱讀 899評(píng)論 0 6
  • 0. 前言 說(shuō)到AJAX就會(huì)不可避免的面臨兩個(gè)問(wèn)題。 AJAX以何種格式來(lái)交換數(shù)據(jù)? 第二個(gè)是跨域的需求如何解決?...
    公子七閱讀 23,669評(píng)論 7 67
  • 五十三:請(qǐng)解釋 JavaScript 中 this 是如何工作的。1.方法調(diào)用模式當(dāng)一個(gè)函數(shù)被保存為一個(gè)對(duì)象的屬性...
    Arno_z閱讀 596評(píng)論 0 2
  • 愛(ài)情這東西吧,其實(shí)還真是很玄乎著呢。 你愛(ài)的不一定愛(ài)你,你不愛(ài)的卻死皮賴臉的粘著你,所以那種兩情相悅的愛(ài)情便顯得難...
    大耳朵屁屁閱讀 279評(píng)論 0 1