jsonp跨域?qū)嵺`(附其他實(shí)現(xiàn)跨域的方法)

面試中常常會(huì)問(wèn)到如何使用jsonp跨域(jsonp跨域的原理是什么)燕偶,這篇文章就給大家介紹一下相關(guān)的知識(shí)指么,如有不對(duì)榴鼎,麻煩指出 ~

1. 首先我們比較一下json和jsonp
  • JSON是一種基于文本的數(shù)據(jù)交換方式,或者叫做數(shù)據(jù)描述格式巫财;
  • JSONP是一種非官方跨域數(shù)據(jù)交互協(xié)議;
2.為什么會(huì)出現(xiàn)jsonp
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)簽都擁有跨域的能力癣籽,比如<script>、<img>筷狼、<iframe>)匠童。
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é)議,人們把它稱(chēng)作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ù)了。

3.jsonp實(shí)現(xiàn)例子

  • 假設(shè)遠(yuǎn)程的服務(wù)器remoteServer.com上有一段js文件娶耍,內(nèi)容為:
alert("hello world");

我們本地localhost.com上有一個(gè)頁(yè)面,里面引入了上面的js文件榕酒,當(dāng)我們?cè)跒g覽器中打開(kāi)此頁(yè)面時(shí),會(huì)發(fā)現(xiàn)可以成功的彈出hello world紊婉,這就表示跨域調(diào)用成功了辑舷。

  • 如何跨域遠(yuǎn)程獲取數(shù)據(jù)呢
    本地localhost.com上有一個(gè)頁(yè)面localhost.html,頁(yè)面內(nèi)容為:
<html>
  <head> 
    <title></title> 
    <script type="text/javascript"> 
      var localHandler = function(data){ 
          alert('我是本地函數(shù)何缓,可以被跨域的remote.js文件調(diào)用,遠(yuǎn)程js帶來(lái)的數(shù)據(jù)是:' + data.result); 
      };                  
    </script> 
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
    </head>
<body>
</body>
</html>

remoteserver.com上的remote.js文件內(nèi)容:

localHandler({"result":"hello world"});

我們?cè)跒g覽器中打開(kāi)此頁(yè)面localhost.html乔妈,發(fā)現(xiàn)彈出了

我是本地函數(shù)氓皱,可以被跨域的remote.js文件調(diào)用,遠(yuǎn)程js帶來(lái)的數(shù)據(jù)是:hello world
跨域遠(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ù)都不相同啊敛瓷?

<br >

  • 解決遠(yuǎn)程服務(wù)器不知道該調(diào)用什么函數(shù)的問(wèn)題

思路:只要服務(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)了庶橱。

再看 localhost.html

<html>
  <head> 
    <title></title> 
    <script type="text/javascript"> 
       // 得到航班信息查詢結(jié)果后的回調(diào)函數(shù) 
      var flightHandler = function(data){ 
          alert('你查詢的航班結(jié)果是:票價(jià) ' + data.price + ' 元贪惹,' + '余票 ' + data.tickets + ' 張。'); 
      };
       // 提供jsonp服務(wù)的url地址(不管是什么類(lèi)型的地址,最終生成的返回值都是一段javascript代碼) 
      var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; 
      // 創(chuàng)建script標(biāo)簽垫释,設(shè)置其屬性 
      var script = document.createElement('script'); 
      script.setAttribute('src', url); 
      // 把script標(biāo)簽加入head,此時(shí)調(diào)用開(kāi)始
      document.getElementsByTagName('head')[0].appendChild(script); 
    </script> 
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
    </head>
<body>
</body>
</html>

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

{
  "code": "CA1998", 
  "price": 1780,
   "tickets": 5
}
  • 封裝代碼,jquery實(shí)現(xiàn)jsonp
<html>
 <head>
     <title>Untitled Page</title>
      <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
        // 得到航班信息查詢結(jié)果后的回調(diào)函數(shù)  
        var flightHandler = function(data){ alert('你查詢的航班結(jié)果是:票價(jià) ' + data.price + ' 元神郊,' + '余票 ' + data.tickets + ' 張趾唱。'); };

        jQuery(document).ready(function(){
          $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//傳遞給請(qǐng)求處理程序或頁(yè)面的,用以獲得jsonp回調(diào)函數(shù)名的參數(shù)名(一般默認(rèn)為:callback)
             jsonpCallback:"flightHandler",//自定義的jsonp回調(diào)函數(shù)名稱(chēng)夕晓,默認(rèn)為jQuery自動(dòng)生成的隨機(jī)函數(shù)名悠咱,也可以寫(xiě)"?",jQuery會(huì)自動(dòng)為你處理數(shù)據(jù)
             success: function(json){
                 alert('您查詢到航班信息:票價(jià): ' + json.price + ' 元析既,余票: ' + json.tickets + ' 張。');
             },
             error: function(){
                 alert('fail');
             }
           });
         });
     </script>
 </head>
 <body>
 </body>
</html>

jquery幫你生成回調(diào)函數(shù)并把數(shù)據(jù)取出來(lái)供success屬性方法來(lái)調(diào)用逗宜。

附其他實(shí)現(xiàn)跨域的方法:
  • document.domain+iframe的設(shè)置
  • 動(dòng)態(tài)創(chuàng)建script
  • 利用iframe和location.hash
  • window.name實(shí)現(xiàn)的跨域數(shù)據(jù)傳輸
  • 使用HTML5 postMessage
  • 利用flash
    詳細(xì)介紹,點(diǎn)擊這里

參考文章:說(shuō)說(shuō)JSON和JSONP擂仍,也許你會(huì)豁然開(kāi)朗熬甚,含jQuery用例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市肃廓,隨后出現(xiàn)的幾起案子诲泌,更是在濱河造成了極大的恐慌,老刑警劉巖敷扫,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葵第,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡卒密,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)将硝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)屏镊,“玉大人,你說(shuō)我怎么就攤上這事而芥。” “怎么了误辑?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵巾钉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我秘案,道長(zhǎng)潦匈,這世上最難降的妖魔是什么赚导? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任吼旧,我火速辦了婚禮,結(jié)果婚禮上圈暗,老公的妹妹穿的比我還像新娘。我一直安慰自己员串,他們只是感情好勇哗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布智绸。 她就那樣靜靜地躺著访忿,像睡著了一般斯稳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上卧斟,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天憎茂,我揣著相機(jī)與錄音,去河邊找鬼竖幔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛募逞,可吹牛的內(nèi)容都是我干的馋评。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼纠脾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼玛瘸!你這毒婦竟也來(lái)了捧韵?” 一聲冷哼從身側(cè)響起汉操,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤磷瘤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后采缚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡篡帕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年贸呢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怔鳖。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡结执,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出艾凯,到底是詐尸還是另有隱情,我是刑警寧澤趾诗,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站沧竟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏杈笔。R本人自食惡果不足惜糕非,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一球榆、第九天 我趴在偏房一處隱蔽的房頂上張望持钉。 院中可真熱鬧,春花似錦篱昔、人聲如沸每强。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)空执。三九已至,卻和暖如春穗椅,著一層夾襖步出監(jiān)牢的瞬間辨绊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工匹表, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留门坷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓袍镀,卻偏偏與公主長(zhǎng)得像默蚌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子流椒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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