理解Ajax

什么是Ajax弥雹?

AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。意思就是用JavaScript執(zhí)行異步網(wǎng)絡(luò)請求珍特。
AJAX 不是新的編程語言,而是一種使用現(xiàn)有標(biāo)準(zhǔn)的新方法魔吐。
AJAX 最大的優(yōu)點是在不重新加載整個頁面的情況下,可以與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁內(nèi)容。
AJAX 不需要任何瀏覽器插件赦颇,但需要用戶允許JavaScript在瀏覽器上執(zhí)行。

如果仔細(xì)觀察一個Form提交奥溺,你就會發(fā)現(xiàn),一旦用戶點擊"submit"按鈕骨宠,表單開始提交浮定,瀏覽器就會開始刷新頁面,然后在新頁面里告訴你操作是成功了還是失敗了层亿,如果不幸由于網(wǎng)絡(luò)太慢或者其他原因桦卒,就會得到一個404頁面。

這就是Web的運作原理匿又,一次HTTP請求方灾,對應(yīng)一個頁面。

如果要讓用戶瀏覽當(dāng)前頁面中碌更,同時發(fā)出新的HTTP請求裕偿,就必須用javascript發(fā)送這個新請求,接收到數(shù)據(jù)后痛单,再用JavaScript更新頁面嘿棘,這樣一來,用戶就感覺自己仍然停留在當(dāng)前頁面旭绒,但數(shù)據(jù)卻不斷的更新鸟妙。

最早大規(guī)模使用Ajax的就是Gmail,Gmail的頁面在首次加載后,剩下的所有數(shù)據(jù)挥吵,都依賴于Ajax來更新重父。

用JavaScript來寫一個完成的Ajax代碼并不復(fù)雜,但是需要注意:Ajax請求是異步執(zhí)行的蔫劣,也就是說坪郭,要通過回調(diào)函數(shù)獲得響應(yīng)个从。

Ajax創(chuàng)建流程

一:創(chuàng)建XMLHttpRequest對象(標(biāo)準(zhǔn)寫法和IE寫法混在一起)

        var xhr;
        //現(xiàn)代瀏覽器
        if(window.XMLHttpRequest){
            xhr = new XMLHttpRequset();
        }else{
            //低版本IE瀏覽器脉幢,需要ActiveXObject
            xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }

二:對xhr進行配置

         xhr.open("傳輸方式GET或POST","網(wǎng)址","是否異步");

三:發(fā)送網(wǎng)絡(luò)請求

         xhr.send();

四:監(jiān)聽網(wǎng)絡(luò)請求狀態(tài),并接收網(wǎng)絡(luò)返回的數(shù)據(jù)

         xhr.onreadystatechange=function(){
          if(xhr.readyState===4){    //成功完成
          //判斷響應(yīng)結(jié)果
          if((xhr.status>=200&&xhr.status<300)||xhr.status===304){
                // 成功嗦锐,通過responseText拿到響應(yīng)的文本:
                console.log(xhr.responseText);
           }else {
                // 失敗嫌松,根據(jù)響應(yīng)碼判斷失敗原因:
                console.log(xhr.status)
            }
        }
      }

注意:

  1. status存儲的是HTTP狀態(tài)碼,狀態(tài)碼都是服務(wù)器發(fā)過來的,表示的是服務(wù)器狀態(tài)
    200 - OK 一切正常奕污,對GET和POST請求的應(yīng)答文檔跟在后面
    304 - Not Modified 客戶端有緩沖的文檔并發(fā)出了一個條件性的請求,服務(wù)器告訴客戶萎羔,原來緩沖的文檔還可以繼續(xù)使用。
    400 - Bad Request 請求出現(xiàn)語法錯誤碳默。
    404 - Not Found 無法找到指定位置的資源贾陷。這也是一個常用的應(yīng)答缘眶。

  2. XMLHttpRequest.readyState 屬性返回一個 XMLHttpRequest 代理當(dāng)前所處的狀態(tài)。一個 XHR 代理總是處于下列狀態(tài)中的一個:


    image.png

注意:

  • 通過檢測window對象是否有XMLHttpRequest屬性來確定瀏覽器是否支持標(biāo)準(zhǔn)的XMLHttpRequest髓废。注意巷懈,不要根據(jù)瀏覽器的navigator.userAgent來檢測瀏覽器是否支持某個JavaScript特性,一是因為這個字符串本身可以偽造慌洪,二是通過IE版本判斷JavaScript特性將非常復(fù)雜顶燕。

  • 當(dāng)創(chuàng)建了XMLHttpRequest對象后,要先設(shè)置onreadystatechange的回調(diào)函數(shù)冈爹。在回調(diào)函數(shù)中涌攻,通常我們只需通過readyState === 4判斷請求是否完成,如果已完成频伤,再根據(jù)status === 200判斷是否是一個成功的響應(yīng)恳谎。

  • XMLHttpRequest對象的open()方法有3個參數(shù),第一個參數(shù)指定是GET還是POST剂买,第二個參數(shù)指定URL地址惠爽,第三個參數(shù)指定是否使用異步,默認(rèn)是true瞬哼,所以不用寫婚肆。

  • 注意,千萬不要把第三個參數(shù)指定為false坐慰,否則瀏覽器將停止響應(yīng)较性,直到AJAX請求完成。如果這個請求耗時10秒结胀,那么10秒內(nèi)你會發(fā)現(xiàn)瀏覽器處于“假死”狀態(tài)赞咙。

  • 最后調(diào)用send()方法才真正發(fā)送請求。GET請求不需要參數(shù)糟港,POST請求需要把body部分以字符串或者FormData對象傳進去攀操。


安全限制

  • 瀏覽器的同源策略,默認(rèn)情況下秸抚,JavaScript在發(fā)送AJAX請求時速和,URL的域名必須和當(dāng)前頁面完全一致。
  • 完全一致的意思是剥汤,域名要相同(www.example.comexample.com不同)颠放,協(xié)議要相同(http和https不同),端口號要相同(默認(rèn)是:80端口吭敢,它和:8080就不同)碰凶。有的瀏覽器口子松一點,允許端口不同,大多數(shù)瀏覽器都會嚴(yán)格遵守這個限制欲低。

那是不是用JavaScript無法請求外域(就是其他網(wǎng)站)的URL了呢辕宏?方法還是有的,大概有這么幾種:

  1. 一是通過Flash插件發(fā)送HTTP請求砾莱,這種方式可以繞過瀏覽器的安全限制匾效,但必須安裝Flash,并且跟Flash交互恤磷。不過Flash用起來麻煩面哼,而且現(xiàn)在用得也越來越少了。

  2. 二是通過在同源域名下架設(shè)一個代理服務(wù)器來轉(zhuǎn)發(fā)扫步,JavaScript負(fù)責(zé)把請求發(fā)送到代理服務(wù)器:

'/proxy?url=http://www.sina.com.cn'

代理服務(wù)器再把結(jié)果返回魔策,這樣就遵守了瀏覽器的同源策略。這種方式麻煩之處在于需要服務(wù)器端額外做開發(fā)河胎。

  1. 第三種方式稱為JSONP闯袒,它有個限制,只能用GET請求游岳,并且要求返回JavaScript政敢。這種方式跨域?qū)嶋H上是利用了瀏覽器允許跨域引用JavaScript資源:
<html>
<head>
    <script src="http://example.com/abc.js"></script>
    ...
</head>
<body>
...
</body>
</html>

JSONP通常以函數(shù)調(diào)用的形式返回,例如胚迫,返回JavaScript內(nèi)容如下:

foo('data');

這樣一來喷户,我們?nèi)绻陧撁嬷邢葴?zhǔn)備好foo()函數(shù),然后給頁面動態(tài)加一個<script>節(jié)點访锻,相當(dāng)于動態(tài)讀取外域的JavaScript資源褪尝,最后就等著接收回調(diào)了。

以163的股票查詢URL為例期犬,對于URL:http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice河哑,你將得到如下返回:

refreshPrice({"0000001":{"code": "0000001", ... });

因此我們需要首先在頁面中準(zhǔn)備好回調(diào)函數(shù):

function refreshPrice(data) {
    var p = document.getElementById('test-jsonp');
    p.innerHTML = '當(dāng)前價格:' +
        data['0000001'].name +': ' + 
        data['0000001'].price + ';' +
        data['1399001'].name + ': ' +
        data['1399001'].price;
}

當(dāng)前價格:上證指數(shù): 2606.91龟虎;深證成指: 7558.277

最后用getPrice()函數(shù)觸發(fā):

function getPrice() {
    var
        js = document.createElement('script'),
        head = document.getElementsByTagName('head')[0];
    js.src = 'http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice';
    head.appendChild(js);
}

就完成了跨域加載數(shù)據(jù)璃谨。

CORS

如果瀏覽器支持HTML5,那么就可以一勞永逸地使用新的跨域策略:CORS了鲤妥。

CORS全稱Cross-Origin Resource Sharing佳吞,是HTML5規(guī)范定義的如何跨域訪問資源。

了解CORS前旭斥,我們先搞明白概念:

Origin表示本域容达,也就是瀏覽器當(dāng)前頁面的域古涧。當(dāng)JavaScript向外域(如sina.com)發(fā)起請求后垂券,瀏覽器收到響應(yīng)后,首先檢查Access-Control-Allow-Origin是否包含本域,如果是菇爪,則此次跨域請求成功算芯,如果不是,則請求失敗凳宙,JavaScript將無法獲取到響應(yīng)的任何數(shù)據(jù)熙揍。

用一個圖來表示就是


image.png

假設(shè)本域是my.com,外域是sina.com氏涩,只要響應(yīng)頭Access-Control-Allow-Origin為http://my.com届囚,或者是*,本次請求就可以成功是尖。

可見意系,跨域能否成功,取決于對方服務(wù)器是否愿意給你設(shè)置一個正確的Access-Control-Allow-Origin饺汹,決定權(quán)始終在對方手中蛔添。

上面這種跨域請求,稱之為“簡單請求”兜辞。簡單請求包括GET迎瞧、HEAD和POST(POST的Content-Type類型
僅限application/x-www-form-urlencoded、multipart/form-data和text/plain)逸吵,并且不能出現(xiàn)任何自定義頭(例如凶硅,X-Custom: 12345),通常能滿足90%的需求扫皱。

無論你是否需要用JavaScript通過CORS跨域請求資源咏尝,你都要了解CORS的原理。最新的瀏覽器全面支持HTML5啸罢。在引用外域資源時编检,除了JavaScript和CSS外,都要驗證CORS扰才。例如允懂,當(dāng)你引用了某個第三方CDN上的字體文件時:

/* CSS */
@font-face {
  font-family: 'FontAwesome';
  src: url('http://cdn.com/fonts/fontawesome.ttf') format('truetype');
}

如果該CDN服務(wù)商未正確設(shè)置Access-Control-Allow-Origin,那么瀏覽器無法加載字體資源衩匣。

對于PUT蕾总、DELETE以及其他類型如application/json的POST請求,在發(fā)送AJAX請求之前琅捏,瀏覽器會先發(fā)送一個OPTIONS請求(稱為preflighted請求)到這個URL上生百,詢問目標(biāo)服務(wù)器是否接受:

OPTIONS /path/to/resource HTTP/1.1
Host: bar.com
Origin: http://my.com
Access-Control-Request-Method: POST

服務(wù)器必須響應(yīng)并明確指出允許的Method:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://my.com
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS
Access-Control-Max-Age: 86400

瀏覽器確認(rèn)服務(wù)器響應(yīng)的Access-Control-Allow-Methods頭確實包含將要發(fā)送的AJAX請求的Method,才會繼續(xù)發(fā)送AJAX柄延,否則蚀浆,拋出一個錯誤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市市俊,隨后出現(xiàn)的幾起案子杨凑,更是在濱河造成了極大的恐慌,老刑警劉巖摆昧,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撩满,死亡現(xiàn)場離奇詭異,居然都是意外死亡绅你,警方通過查閱死者的電腦和手機伺帘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忌锯,“玉大人曼追,你說我怎么就攤上這事『汗妫” “怎么了礼殊?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長针史。 經(jīng)常有香客問我晶伦,道長,這世上最難降的妖魔是什么啄枕? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任婚陪,我火速辦了婚禮,結(jié)果婚禮上频祝,老公的妹妹穿的比我還像新娘泌参。我一直安慰自己,他們只是感情好常空,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布沽一。 她就那樣靜靜地躺著,像睡著了一般漓糙。 火紅的嫁衣襯著肌膚如雪铣缠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天昆禽,我揣著相機與錄音蝗蛙,去河邊找鬼。 笑死醉鳖,一個胖子當(dāng)著我的面吹牛捡硅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盗棵,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼壮韭,長吁一口氣:“原來是場噩夢啊……” “哼北发!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泰涂,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辐怕,沒想到半個月后逼蒙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡寄疏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年是牢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陕截。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡驳棱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出农曲,到底是詐尸還是另有隱情社搅,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布乳规,位于F島的核電站形葬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏暮的。R本人自食惡果不足惜笙以,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望冻辩。 院中可真熱鬧猖腕,春花似錦、人聲如沸恨闪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咙咽。三九已至侠仇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間犁珠,已是汗流浹背逻炊。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留犁享,地道東北人余素。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像炊昆,于是被迫代替她去往敵國和親桨吊。 傳聞我的和親對象是個殘疾皇子威根,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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

  • ajax的工作原理: ajax的工作原理相當(dāng)于在用戶和服務(wù)器之間加了一個中間層(ajax引擎),使用戶操作與服務(wù)器...
    L怪丫頭閱讀 327評論 0 3
  • 深入理解Ajax ajax的工作原理: ajax的工作原理相當(dāng)于在用戶和服務(wù)器之間加了一個中間層(ajax引擎)视乐,...
    AjingA閱讀 572評論 0 1
  • 本文詳細(xì)介紹了 XMLHttpRequest 相關(guān)知識洛搀,涉及內(nèi)容: AJAX、XMLHTTP佑淀、XMLHttpReq...
    semlinker閱讀 13,662評論 2 18
  • ajax的工作原理: ajax的工作原理相當(dāng)于在用戶和服務(wù)器之間加了一個中間層(ajax引擎) 留美,使用 戶操作與服...
    十___閱讀 512評論 0 3
  • 概念 ajax 的全稱是AsynchronousJavaScript and XML,其中伸刃,Asynchronou...
    一個敲代碼的前端妹子閱讀 675評論 3 1