jquery中的ajax處理跨域的三大方法

一陷寝、處理跨域的方式:

1.代理
2.XHR2

HTML5中提供的XMLHTTPREQUEST Level2(及XHR2)已經(jīng)實現(xiàn)了跨域訪問想罕。但ie10以下不支持
只需要在服務(wù)端填上響應(yīng)頭硫眨。

  header("Access-Control-Allow-Origin:*");
 /*星號表示所有的域都可以接受,*/
header("Access-Control-Allow-Methods:GET,POST");
3.jsonP

原理:ajax本身是不可以跨域的尖滚,通過產(chǎn)生一個script標簽來實現(xiàn)跨域档冬。因為script標簽的src屬性是沒有跨域的限制的。
其實設(shè)置了dataType: 'jsonp'后薪夕,$.ajax方法就和ajax XmlHttpRequest沒什么關(guān)系了脚草,取而代之的則是JSONP協(xié)議。JSONP是一個非官方的協(xié)議原献,它允許在服務(wù)器端集成Script tags返回至客戶端馏慨,通過javascript callback的形式實現(xiàn)跨域訪問。
ajax的跨域?qū)懛ǎ?/p>

/*當前網(wǎng)址是localhost:3000*/
js代碼
$.ajax({
type:
"get",
 url:"[http://localhost:3000/showAll](http://localhost:3000/showAll)"/*url寫異域的請求地址*/
dataType:"jsonp",/*加上datatype*/
jsonpCallback:"cb",/*設(shè)置一個回調(diào)函數(shù)姑隅,名字隨便取写隶,和下面的函數(shù)里的名字相同就行*/
success:function(){
。讲仰。慕趴。
}
});
/*而在異域服務(wù)器上,*/

app.js
app.get('/showAll',students.showAll);/*這和不跨域的寫法相同*/

/*在異域服務(wù)器的showAll函數(shù)里鄙陡,*/
var db = require("./database");
exports.showAll =function(req,res){ 
/**設(shè)置響應(yīng)頭允許ajax跨域訪問**/
res.setHeader("Access-Control-Allow-Origin","*");
/*星號表示所有的異域請求都可以接受冕房,*/
res.setHeader("Access-Control-Allow-Methods","GET,POST"); 
var con = db.getCon();
con.query("select * from t_students",function(error,rows){
if(error){
console.log("數(shù)據(jù)庫出錯:"+error);
}else{
/*注意這里,返回的就是jsonP的回調(diào)函數(shù)名+數(shù)據(jù)了*/
res.send("cb("+JSON.stringify(r)+")");
 }
});
}

二趁矾、解決ajax跨域訪問耙册、 JQuery 的跨域方法

JS的跨域問題,我想很多程序員的腦海里面還認為JS是不能跨域的毫捣,其實這是一個錯誤的觀點详拙;有很多人在網(wǎng)上找其解決方法,教其用IFRAME去解決的文章很多蔓同,真有那么復(fù)雜嗎饶辙?其實很簡單的,如果你用JQUERY牌柄,一個GETJSON方法就搞定了畸悬,而且是一行代碼搞定
下面開始貼出方法

//跨域(可跨所有域名)
$.getJSON("[http://user.hnce.com.cn/getregion.aspx?id=0&jsoncallback=?](http://user.hnce.com.cn/getregion.aspx?id=0&jsoncallback=?)",function(json){//要求遠程請求頁面的數(shù)據(jù)格式為: ?(json_data)
 //例如: //?([{"_name":"湖南省","_regionId":134},{"_name":"北京市","_regionId":143}]) alert(json[0]._name);});

$.getJSON("[http://user.hnce.com.cn/getregion.aspx?id=0&jsoncallback=?](http://user.hnce.com.cn/getregion.aspx?id=0&jsoncallback=?)",
function(json){//要求遠程請求頁面的數(shù)據(jù)格式為: ?(json_data)
 //例如: //?([{"_name":"湖南省","_regionId":134},{"_name":"北京市","_regionId":143}]) alert(json[0]._name);
});

注意侧甫,getregion.aspx中珊佣,在輸出JSON數(shù)據(jù)時,一定要用Request.QueryString["jsoncallback"]披粟,將獲取的內(nèi)容放到返回JSON數(shù)據(jù)的前面咒锻,假設(shè)實際獲取的值為42342348,那么返回的值就是 42342348([{"_name":"湖南省","_regionId":134},{"_name":"北京市","_regionId":143}])
因為getJSON跨域的原理是把守屉?隨機變一個方法名惑艇,然后返回執(zhí)行的,實現(xiàn)跨域響應(yīng)的目的。
下面一個是跨域執(zhí)行的真實例子:

<script src="[http://common.cnblogs.com/script/jquery.js(http://common.cnblogs.com/script/jquery.js)"type="text/javascript"></script>

<script type="text/javascript">
//跨域(可跨所有域名)
$.getJSON("[http://e.hnce.com.cn/tools/ajax.aspx?jsoncallback=?](http://e.hnce.com.cn/tools/ajax.aspx?jsoncallback=?)", { id: 0, action:'jobcategoryjson'},function(json) { alert(json[0].pid); alert(json[0].items[0]._name); }); 
 </script>

實例2

   <script src="[http://common.cnblogs.com/script/jquery.js](http://common.cnblogs.com/script/jquery.js)"type="text/javascript"></script>
<script type="text/javascript">
//跨域(可跨所有域名)
$.getJSON("[http://e.hnce.com.cn/tools/ajax.aspx?jsoncallback=?](http://e.hnce.com.cn/tools/ajax.aspx?jsoncallback=?)", { id: 0, action:'jobcategoryjson'
},function(json) { alert(json[0].pid); alert(json[0].items[0]._name); });  
</script>

jQuery跨域原理:
瀏覽器會進行同源檢查,這導(dǎo)致了跨域問題,然而這個跨域檢查還有一個例外那就是HTML的<Script>標記;我們經(jīng)常使用<Script>的src屬性,腳本靜態(tài)資源放在獨立域名下或者來自其它站點的時候這里是一個url;這個url響應(yīng)的結(jié)果可以有很多種,比如JSON,返回的Json值成為<Script>標簽的src屬性值.這種屬性值變化并不會引起頁面的影響.按照慣例滨巴,瀏覽器在URL的查詢字符串中提供一個參數(shù)思灌,這個參數(shù)將作為結(jié)果的前綴一起返回到瀏覽器;
看下面的例子:

<script type="text/javascript"src="[http://domain2.com/getjson?jsonp=parseResponse](http://domain2.com/getjson?jsonp=parseResponse)"></script>
響應(yīng)值:parseResponse({"Name":"Cheeso","Rank": 7})
<script type="text/javascript"src="[http://domain2.com/getjson?jsonp=parseResponse](http://domain2.com/getjson?jsonp=parseResponse)"></script>
響應(yīng)值:parseResponse({"Name":"Cheeso","Rank": 7})

這種方式被稱作JsonP;(如果鏈接已經(jīng)失效請點擊這里:JSONP);即:JSON with padding 上面提到的前綴就是所謂的“padding”。那么jQuery里面是怎么實現(xiàn)的呢恭取?
貌似并沒有<Script>標記的出現(xiàn)L┏ァ?OKay蜈垮,翻看源碼來看:
頁面調(diào)用的是getJSON:

getJSON: function( url, data, callback ) {
 return jQuery.get(url, data, callback, "json");
 },

繼續(xù)跟進

get: function( url, data, callback, type ) {
// shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) {
 type = type || callback;
callback = data;
data = null;
  }

 return jQuery.ajax({
 type: "GET",
 url: url,
 data: data,
 success: callback,
 dataType: type
});

跟進jQuery.ajax耗跛,下面是ajax方法的代碼片段:

// Build temporary JSONP function
if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
jsonp = s.jsonpCallback || ("jsonp" + jsc++);

// Replace the =? sequence both in the query string and the data
if ( s.data ) {
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
}

s.url = s.url.replace(jsre, "=" + jsonp + "$1");

// We need to make sure
// that a JSONP style response is executed properly
s.dataType = "script";

// Handle JSONP-style loading
window[ jsonp ] = window[ jsonp ] || function( tmp ) {
data = tmp;
success();
complete();
// Garbage collect
window[ jsonp ] = undefined;

try {
 delete window[ jsonp ];
} catch(e) {}

if ( head ) {
 head.removeChild( script );
}
};
}

if ( s.dataType === "script" && s.cache === null ) {
s.cache = false;
}

if ( s.cache === false && type === "GET" ) {
var ts = now();

// try replacing _= if it is there
var ret = s.url.replace(rts, "$1_=" + ts + "$2");

// if nothing was replaced, add timestamp to the end
s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
}

// If data is available, append data to url for get requests
if ( s.data && type === "GET" ) {
s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
}

// Watch for a new set of requests
if ( s.global && ! jQuery.active++ ) {
jQuery.event.trigger( "ajaxStart" );
}

// Matches an absolute URL, and saves the domain
var parts = rurl.exec( s.url ),
remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !==     location.host);

// If we're requesting a remote document
// and trying to load JSON or Script with a GET
if ( s.dataType === "script" && type === "GET" && remote ) {
  var head = document.getElementsByTagName("head")[0] ||document.documentElement;
var script = document.createElement("script");
script.src = s.url;
if ( s.scriptCharset ) {
script.charset = s.scriptCharset;
}

// Handle Script loading
if ( !jsonp ) {
var done = false;

// Attach handlers for all browsers
script.onload = script.onreadystatechange = function() {
 if ( !done && (!this.readyState ||
 this.readyState === "loaded" || this.readyState === "complete") ) {
 done = true;
 success();
 complete();

 // Handle memory leak in IE
 script.onload = script.onreadystatechange = null;
 if ( head && script.parentNode ) {
 head.removeChild( script );
 }
 }
};
}

// Use insertBefore instead of appendChild to circumvent an IE6 bug.
// This arises when a base node is used (#2709 and #4378).
head.insertBefore( script, head.firstChild );

// We handle everything using the script element injection
return undefined;
}

上面的代碼第1行到第10行:判斷是JSON類型調(diào)用,為本次調(diào)用創(chuàng)建臨時的JsonP方法攒发,并且添加了一個隨機數(shù)字调塌,這個數(shù)字源于用日期值;
關(guān)注第14行惠猿,這一行相當關(guān)鍵羔砾,注定了我們的結(jié)果最終是<Script> ;然后是構(gòu)造Script片段,第95行在Head中添加該片段偶妖,修成正果蜒茄;
不僅僅是jQuery,很多js框架都是用了同樣的跨域方案,這就是getJSON跨域的原理餐屎。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末檀葛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子腹缩,更是在濱河造成了極大的恐慌屿聋,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藏鹊,死亡現(xiàn)場離奇詭異润讥,居然都是意外死亡,警方通過查閱死者的電腦和手機盘寡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門楚殿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人竿痰,你說我怎么就攤上這事脆粥。” “怎么了影涉?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵变隔,是天一觀的道長。 經(jīng)常有香客問我蟹倾,道長匣缘,這世上最難降的妖魔是什么猖闪? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮肌厨,結(jié)果婚禮上培慌,老公的妹妹穿的比我還像新娘。我一直安慰自己柑爸,他們只是感情好检柬,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著竖配,像睡著了一般何址。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上进胯,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天用爪,我揣著相機與錄音,去河邊找鬼胁镐。 笑死偎血,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的盯漂。 我是一名探鬼主播颇玷,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼就缆!你這毒婦竟也來了帖渠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤竭宰,失蹤者是張志新(化名)和其女友劉穎空郊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體切揭,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡狞甚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了廓旬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哼审。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖孕豹,靈堂內(nèi)的尸體忽然破棺而出涩盾,到底是詐尸還是另有隱情,我是刑警寧澤巩步,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布旁赊,位于F島的核電站桦踊,受9級特大地震影響椅野,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一竟闪、第九天 我趴在偏房一處隱蔽的房頂上張望离福。 院中可真熱鬧,春花似錦炼蛤、人聲如沸妖爷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽絮识。三九已至,卻和暖如春嗽上,著一層夾襖步出監(jiān)牢的瞬間次舌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工兽愤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留彼念,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓浅萧,卻偏偏與公主長得像逐沙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子洼畅,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

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