亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳細(xì)分析jsonp的原理和實(shí)現(xiàn)方式

 更新時(shí)間:2017年11月20日 11:11:41   投稿:laozhang  
給大家圖文詳細(xì)分析一下jsonp的原理以及跨域問(wèn)題的匯總。

針對(duì)跨域問(wèn)題,本文主要給大家詳細(xì)分析一下jsonp的原理,希望能夠給你提供到幫助。

詳細(xì)分析jsonp的原理和實(shí)現(xiàn)方式

一:跨域問(wèn)題。

二,跨域產(chǎn)生的原因

Js是不能跨域請(qǐng)求。出于安全考慮,js設(shè)計(jì)時(shí)不可以跨域。

什么是跨域:

1、域名不同時(shí)。

2、域名相同,端口不同。

只有域名相同、端口相同時(shí),才可以訪問(wèn)。

可以使用jsonp解決跨域問(wèn)題。

三,跨域失敗的案例 3.1,同源策略

首先基于安全的原因,瀏覽器是存在同源策略這個(gè)機(jī)制的,同源策略阻止從一個(gè)源加載的文檔或腳本獲取或設(shè)置另一個(gè)源加載的文檔的屬性??雌饋?lái)不知道什么意思,實(shí)踐一下就知道了。

3.2,隨便建兩個(gè)網(wǎng)頁(yè)

一個(gè)端口是2698,一個(gè)2701,按照定義它們是不同源的。

3.3,用jQuery發(fā)起不同源的請(qǐng)求

在2698端口的網(wǎng)頁(yè)上添加一個(gè)按鈕,Click事件隨便發(fā)起兩個(gè)向端口為2701域的請(qǐng)求。

$("#getOtherDomainThings").click(function () {
$.get("http://localhost:2701/Scripts/jquery-1.4.4.min.js", function (data) {
console.log(data)
})

$.get("http://localhost:2701/home/index", function (data) {
console.log(data)
})
})

根據(jù)同源策略,很明顯會(huì)悲劇了。瀏覽器會(huì)阻止,根本不會(huì)發(fā)起這個(gè)請(qǐng)求。(not allowed by Access-Control-Allow-Origin)

OK,原來(lái)jsonp是要解決這個(gè)問(wèn)題的。

換句話就是說(shuō)在一個(gè)src中或者一個(gè)url中直接去請(qǐng)求了另一個(gè)項(xiàng)目的json數(shù)據(jù)。

例如在端口是8080的項(xiàng)目中的頁(yè)面的url中直接去請(qǐng)求了一個(gè)http://localhost:8081/category.json這個(gè)語(yǔ)句,而這個(gè)category.json就在8081的webapp的目錄下,就會(huì)產(chǎn)生跨域請(qǐng)求的提示。

四,跨域的解決方法 4.1,啟發(fā)

我們有時(shí)候在項(xiàng)目中經(jīng)常能看到這樣的代碼

<script type="text/javascript" src="https://com/seashell/weixin/js/jquery.js"></script>

這樣即使不在同一個(gè)項(xiàng)目中,也可以請(qǐng)求成功。就是利用了這個(gè)漏洞,或者說(shuō)是技術(shù)吧,來(lái)實(shí)現(xiàn)的寬裕的請(qǐng)求。

4.2,方法(案例一) 4.2.1,利用script獲取不同源的json

既然它叫jsonp,很明顯目的還是json,而且是跨域獲取。根據(jù)上面的分析,很容易想到:利用js構(gòu)造一個(gè)script標(biāo)簽,把json的url賦給script的scr屬性,把這個(gè)script插入到dom里,讓瀏覽器去獲取。實(shí)踐:

function CreateScript(src) {
 $("<script><//script>").attr("src", src).appendTo("body")
}

添加一個(gè)按鈕事件來(lái)測(cè)試一下:

$("#getOtherDomainJson").click(function () {
 $.get('http://localhost:2701/home/somejson', function (data) {
  console.log(data)
 })
})

首先,第一個(gè)瀏覽器,http://localhost:2701/home/somejson這個(gè)Url的確是存在一個(gè)json的,而且在 2698網(wǎng)頁(yè)上用script標(biāo)簽來(lái)請(qǐng)求這個(gè)2701這個(gè)Url也是200OK的,但是最下面報(bào)js語(yǔ)法錯(cuò)誤了。原來(lái)用script標(biāo)簽加載完后,會(huì)立即 把響應(yīng)當(dāng)js去執(zhí)行,很明顯{"Email":"zhww@outlook.com","Remark":"我來(lái)自遙遠(yuǎn)的東方"}不是合法的js語(yǔ)句。

4.2.2,利用script獲取異域的jsonp

顯然,把上面的json放到一個(gè)回調(diào)方法里是最簡(jiǎn)單的方法。例如,變成這樣:

如果存在jsonpcallback這個(gè)方法,那么jsonpcallback({"Email":"zhww@outlook.com","Remark":"我來(lái)自遙遠(yuǎn)的東方"})就是合法的js語(yǔ)句。

在這里需要注意的就是在原來(lái)的json格式的數(shù)據(jù){"Email":"zhww@outlook.com","Remark":"我來(lái)自遙遠(yuǎn)的東方"}要封裝成jsonpcallback({"Email":"zhww@outlook.com","Remark":"我來(lái)自遙遠(yuǎn)的東方"})這樣一個(gè)腳本,這樣才會(huì)被回調(diào)的時(shí)候解析到,否則解析也是失敗的。

由于服務(wù)器不知道客戶端的回調(diào)是什么,不可能hard code成jsonpcallback,所以就帶一個(gè)QueryString讓客戶端告訴服務(wù)端,回調(diào)方法是什么,當(dāng)然,QueryString的key要遵從服務(wù)端的約定,上面的是”callback“。

添加回調(diào)函數(shù):

function jsonpcallback(json) {
 console.log(json)
}

把前面的方法稍微改改參數(shù):

$("#getJsonpByHand").click(function () {
 CreateScript("http://localhost:2701/home/somejsonp?callback=jsonpcallback")
})

200OK,服務(wù)器返回jsonpcallback({"Email":"zhww@outlook.com","Remark":"我來(lái)自遙遠(yuǎn)的 東方"}),我們也寫了jsonpcallback方法,當(dāng)然會(huì)執(zhí)行。OK順利獲得了json。沒(méi)錯(cuò),到這里就是jsonp的全部。

4.2.3,利用jQuery獲取jsonp

上面的方式中,又要插入script標(biāo)簽,又要定義一個(gè)回調(diào),略顯麻煩,利用jQuery可以直接得到想要的json數(shù)據(jù),同樣是上面的jsonp:

$("#getJsonpByJquery").click(function () {
$.ajax({
url: 'http://localhost:2701/home/somejsonp',
dataType: "jsonp",
jsonp: "callback",
success: function (data) {
console.log(data)
}
})
})

得到的結(jié)果跟上面類似。

4.2.4,總結(jié)

一句話就是利用script標(biāo)簽繞過(guò)同源策略,獲得一個(gè)類似這樣的數(shù)據(jù),jsonpcallback是頁(yè)面存在的回調(diào)方法,參數(shù)就是想得到的json。

jsonpcallback({"Email":"zhww@outlook.com","Remark":"我來(lái)自遙遠(yuǎn)的東方"})

4.3,案例二 4.3.1,簡(jiǎn)單應(yīng)用

程序A中sample的部分代碼:

<script type="text/javascript">
//回調(diào)函數(shù)
function callback(data) {
alert(data.message);
}
</script>
<script type="text/javascript" src="http://localhost:20002/test.js"></script>

程序B中test.js的代碼:
1 //調(diào)用callback函數(shù),并以json數(shù)據(jù)形式作為闡述傳遞,完成回調(diào)
2 callback({message:"success"});
這其實(shí)就是JSONP的簡(jiǎn)單實(shí)現(xiàn)模式,或者說(shuō)是JSONP的原型:創(chuàng)建一個(gè)回調(diào)函數(shù),然后在遠(yuǎn)程服務(wù)上調(diào)用這個(gè)函數(shù)并且將JSON 數(shù)據(jù)形式作為參數(shù)傳遞,完成回調(diào)。

將JSON數(shù)據(jù)填充進(jìn)回調(diào)函數(shù),這就是JSONP的JSON+Padding的含義吧。

一般情況下,我們希望這個(gè)script標(biāo)簽?zāi)軌騽?dòng)態(tài)的調(diào)用,而不是像上面因?yàn)楣潭ㄔ趆tml里面所以沒(méi)等頁(yè)面顯示就執(zhí)行了,很不靈活。我們可以通過(guò)javascript動(dòng)態(tài)的創(chuàng)建script標(biāo)簽,這樣我們就可以靈活調(diào)用遠(yuǎn)程服務(wù)了。

4.3.2,簡(jiǎn)單應(yīng)用的升級(jí)以一

程序A中sample的部分代碼:

<script type="text/javascript">
function callback(data) {
alert(data.message);
}
//添加<script>標(biāo)簽的方法
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function(){
addScriptTag("http://localhost:20002/test.js");
}
</script>

程序B的test.js代碼不變,我們?cè)賵?zhí)行下程序,是不是和原來(lái)的一樣呢。如果我們?cè)傧胝{(diào)用一個(gè)遠(yuǎn)程服務(wù)的話,只要添加addScriptTag方法,傳入遠(yuǎn)程服務(wù)的src值就可以了。這里說(shuō)明下為什么要將addScriptTag方法放入到window.onload的方法里,原因是addScriptTag方法中有句document.body.appendChild(script);,這個(gè)script標(biāo)簽是被添加到body里的,由于我們寫的javascript代碼是在head標(biāo)簽中,document.body還沒(méi)有初始化完畢呢,所以我們要通過(guò)window.onload方法先初始化頁(yè)面,這樣才不會(huì)出錯(cuò)。

這樣這個(gè)http://localhost:20002/test.js路徑就可以動(dòng)態(tài)的變化了。

4.3.3,簡(jiǎn)單應(yīng)用的升級(jí)二

上面的例子是最簡(jiǎn)單的JSONP的實(shí)現(xiàn)模型,不過(guò)它還算不上一個(gè)真正的JSONP服務(wù)。我們來(lái)看一下真正的JSONP服務(wù)是怎么樣的,比如Google的ajax搜索接口:http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=?&callback=?

q=?這個(gè)問(wèn)號(hào)是表示你要搜索的內(nèi)容,最重要的是第二個(gè)callback=?這個(gè)是正如其名表示回調(diào)函數(shù)的名稱,也就是將你自己在客戶端定義的回調(diào)函數(shù)的函數(shù)名傳送給服務(wù)端,服務(wù)端則會(huì)返回以你定義的回調(diào)函數(shù)名的方法,將獲取的json數(shù)據(jù)傳入這個(gè)方法完成回調(diào)。有點(diǎn)羅嗦了,還是看看實(shí)現(xiàn)代碼吧:

<script type="text/javascript">//添加<script>標(biāo)簽的方法function addScriptTag(src){ var script = document.createElement('script');script.setAttribute("type","text/javascript");script.src = src;document.body.appendChild(script);}window.onload = function(){//搜索apple,將自定義的回調(diào)函數(shù)名result傳入callback參數(shù)中addScriptTag("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=apple&callback=result");}//自定義的回調(diào)函數(shù)resultfunction result(data) {//我們就簡(jiǎn)單的獲取apple搜索結(jié)果的第一條記錄中url數(shù)據(jù)alert(data.responseData.results[0].unescapedUrl);}</script>

這個(gè)result方法是自己定義的,可能服務(wù)器上有千千萬(wàn)萬(wàn)個(gè)類似于result 的回調(diào)函數(shù),但是我現(xiàn)在要的就是result而不是其它的方法,所以在這里自己定義回調(diào)方法。而不是寫死的??赡芟乱淮挝揖透某蓃esult1,result2,result3,等了只要自己把回調(diào)方法的名稱改一下就行了。

4.4.4,jquery對(duì)jsonp的支持

jQuery框架也當(dāng)然支持JSONP,可以使用$.getJSON(url,[data],[callback])方法(詳細(xì)可以參考http://api.jquery.com/jQuery.getJSON/)。那我們就來(lái)修改下程序A的代碼,改用jQuery的getJSON方法來(lái)實(shí)現(xiàn)(下面的例子沒(méi)用用到向服務(wù)傳參,所以只寫了getJSON(url,[callback])):

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$.getJSON("http://localhost:20002/MyService.ashx?callback=?",function(data){
alert(data.name + " is a a" + data.sex);
});
</script>

結(jié)果是一樣的,要注意的是在url的后面必須添加一個(gè)callback參數(shù),這樣getJSON方法才會(huì)知道是用JSONP方式去訪問(wèn)服務(wù),callback后面的那個(gè)問(wèn)號(hào)是內(nèi)部自動(dòng)生成的一個(gè)回調(diào)函數(shù)名。這個(gè)函數(shù)名大家可以debug一下看看,比如jQuery17207481773362960666_1332575486681。

當(dāng)然,加入說(shuō)我們想指定自己的回調(diào)函數(shù)名,或者說(shuō)服務(wù)上規(guī)定了固定回調(diào)函數(shù)名該怎么辦呢?我們可以使用$.ajax方法來(lái)實(shí)現(xiàn)(參數(shù)較多,詳細(xì)可以參考http://api.jquery.com/jQuery.ajax)。先來(lái)看看如何實(shí)現(xiàn)吧:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$.ajax({
url:"http://localhost:20002/MyService.ashx?callback=?",
dataType:"jsonp",
jsonpCallback:"person",
success:function(data){
alert(data.name + " is a a" + data.sex);
}
});
</script>

沒(méi)錯(cuò),jsonpCallback就是可以指定我們自己的回調(diào)方法名person,遠(yuǎn)程服務(wù)接受callback參數(shù)的值就不再是自動(dòng)生成的回調(diào)名,而是person。dataType是指定按照J(rèn)SOPN方式訪問(wèn)遠(yuǎn)程服務(wù)。

以上就是本次分享關(guān)于jsonp的原理的全部?jī)?nèi)容和代碼,有問(wèn)題的朋友在下方留言討論吧。

相關(guān)文章

最新評(píng)論