您好,登錄后才能下訂單哦!
Ajax是一種技術,一種能夠向服務器請求額外的數據而無需卸載頁面的技術,能夠使網頁具備更優的用戶體驗。Ajax技術的核心是XMLHttpRequest對象(XHR)。本文從XHR開始談起,理解Ajax技術的特點,再對跨域以及Comet等技術進行簡要理解和總結。
XMLHttpRequest基本用法
XHR對象有兩個常用的方法open和send。open方法用戶啟動一個HTTP請求,不過它不會真的發送HTTP請求。open方法接收3個參數,分別表示請求的HTTP方法、請求的URL、是否異步。XHR對象的第二個方法send用于發送open所啟動的請求。send方法接收1個參數,表示HTTP請求的主體數據。如果發送的是GET請求這種沒有附帶主體數據的HTTP請求,則傳入null即可。如果是POST請求,則傳入需要POST的數據。下面是一個簡單示例,向/api/data發起一個GET請求,并且是采取異步的方式發送請求,即該請求不會阻塞頁面中其他js代碼的執行。
var xhr = new XMLHttpRequest() xhr.open("get", "/api/data", true) xhr.send(null)
請求得到的響應數據會自動填充到XHR對象的屬性上,主要有下面4個屬性:
* responseText: 響應主體文本
* responseXML: 如果響應內容類型是"text/xml"或"application/xml", 這個屬性中將包含響應數據的XML DOM文檔
* status: 響應的HTTP狀態碼,一般可以將HTTP狀態嗎200視為成功的標識
* statusText: HTTP狀態的說明
XHR對象有1個readyState屬性記錄了該對象從創建到收到響應數據可能會經歷的5種狀態,readyState的可能取值如下:
0: 還沒有調用open()方法初始化請求
1: 已經調用open()方法但是還沒有調用send()方法
2: 已經調用send()方法但是還沒有收到響應
3: 收到部分響應數據,還有部分數據沒收到
4: 收到全部響應數據,即響應結束,數據完備
當readyState從一個值變到另一個值的時候會觸發readystatechange事件,當這個事件觸發的時候只需要在事件處理器里面檢查一下readyState的值是否為4,當其值為4的時候就可以對響應的數據做后續處理了。給readystatechange事件指定處理器必須在調用open()方法之前完成才能確保跨瀏覽器兼容性。下面是簡單示例。
var xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { console.log(xhr.status, xhr.responseText) } } xhr.open("get", "/api/data", true) xhr.send(null)
XHR對象提供setRequestHeader()方法可以設置請求的自定義HTTP頭部信息,該方法接收兩個參數,要設置的字段和該字段的值。在調用open()啟動一個請求之后并且在send()發送請求之前調用setRequestHeader()才能設置成功。請求得到響應之后,可以通過getResponseHeader()方法獲取響應的HTTP頭部信息,該方法接收1個參數,即要獲取的字段名。而通過getAllResponseHeaders()則可以獲得所有頭部信息組成的長字符串。下面是簡單示例。
var xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { console.log(xhr.status, xhr.responseText) console.log(xhr.getResponseHeader('SomeKey')) console.log(xhr.getAllResponseHeaders()) } } xhr.open("get", "/api/data", true) xhr.setRequestHeader("SomeKey", "SomeValue") xhr.send(null)
FormData
XMLHttpRequest 2級定義了FormData類型為序列化表單、創建與表單格式相同的數據、用于XHR傳輸提供便利。FormData提供append()方法可以直接添加數據,該方法接收兩個參數鍵和值。FormData的構造函數可以不傳參數,也可以直接傳入1個表單元素。傳入表單元素之后會利用該表單元素的數據來向FormData對象預先填入鍵值對。下面是簡單示例。
var form = document.getElementById('myForm') var data = new FormData(form) data.append('someKey', 'someValue') var xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { console.log(xhr.responseText) } } xhr.open('post', '/api/upload', true) xhr.send(data)
跨域資源共享
通過XHR實現Ajax通信會遇到一個限制,即跨域安全策略。跨域安全策略限制了“相同域名、相同端口、相同協議”,當XHR想要訪問限制之外的資源就會引發安全錯誤。CORS(Cross-Origin Resource Sharing),跨域資源共享,其思想是通過使用自定義HTTP頭部讓瀏覽器與服務器進行溝通從而決定請求或者響應的成功與失敗,需要瀏覽器和服務器同時支持才能實現正常的訪問。目前大部分瀏覽器已經支持了CORS,所以寫起代碼跟普通的同域資源訪問幾乎一樣,就只是把URL用絕對路徑表示。因此,要實現跨域的關鍵還是在服務器,具體如何實現本文不深入討論。下面是前端js的簡單示例。
var xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { console.log(xhr.responseText) } } xhr.open('get', 'http://www.otherserver.com/api/data', true) xhr.send(null)
JSONP
JSONP(JSON with padding)是應用JSON實現跨域資源訪問的一種方法。JSONP由兩部分內容組成:回調函數和JSON數據。前面說過,XHR請求會遇到跨域安全策略的限制,但是HTML中的script標簽則不會有這個限制,我們可以通過script標簽引用不同域里面的js文件。JSONP便是鉆了這個空子,它通過動態創建script元素,然后把src指向其他域的URL從而實現加載其他域的資源,然后通過回調函數來處理加載得到的數據。下面是一個簡單示例。
function handler(res) { console.log(res) } var script = document.createElement('script') script.src = 'http://www.otherserver.com/api/data/?callback=handler' document.body.insertBefore(script, document.body.firstChild)
上述代碼指定了動態創建的script元素的src為另一個域名下面的/api/data,然后指明回調函數為handler。將script插入到DOM里面之后會向對應的URL加載數據,完成之后會將得到的JSON數據解析成一個對象并調用handler進行處理。
JSONP是實現跨域訪問的一種簡單的方法,不過也存在一些安全問題,例如請求的其他域的URL響應給你一段惡意代碼。JSONP還有一個問題,script標簽引用的是js,json由于被js所支持所以也可以引用,因此在請求其他域的URL時需要確認它是否以json格式進行響應,而不是XML。
Comet
Ajax是一種從網頁向服務器請求數據的技術,而Comet與之相反,它是從服務器向網頁推送數據的技術,適用于實時性要求比較高的應用。實現Comet的方式有兩種:長輪詢和流。在說長輪詢之前先說一下短輪詢,它的思路很簡單,就是客戶端使用定時器,每隔一定的時間間隔就向服務器發送Ajax請求看看有沒有數據更新,這個時間間隔一般很小。長輪詢同樣也是客戶端不斷向服務器發送請求,不同的是,客戶端不需要按照時間間隔不斷地發送請求,而是發起1個請求到服務器之后,客戶端和服務器之間的HTTP連接保持打開,直到服務器有數據更新就通過這個連接向客戶端響應數據,然后再關閉這個HTTP連接。關閉之后瀏覽器再發起一個新的連接繼續重復前面的過程。相比短輪詢,長輪詢發起的HTTP連接次數更少了,不過如果HTTP連接長時間保持開放也是在占用服務器的資源。
第二種實現Comet的方式是基于HTTP流,客戶端向服務器發起1個HTTP連接,全程保持這個連接打開,客戶端周期性地通過這個連接向服務器獲取數據查看更新。
SSE
SSE(Server-Send Events),服務器發送事件,是一種實現Comet交互的瀏覽器API,支持輪詢也支持HTTP流。SSE API用于創建到服務器的單向連接,服務器通過這個連接可以發送任意數量的數據給客戶端。服務器響應的MIME類型為text/event-stream。下面是SSE的JavaScript API的簡單示例。
var source = new EventSource("/api/events") source.onmessage = function(event) { console.log(event.data) }
如上面代碼所示,要向服務器預定事件流獲取服務器發送的數據,首先創建EventSource對象,然后在message事件觸發的時候進行處理。服務器發送的數據以字符串形式保存在event.data中。EventSource對象會保持與服務器的活動連接,如果中間斷開會重新連接,如果要真正地斷開連接可以通過調用close()方法來實現。EventSource的message事件會在從服務器收到新事件的時候觸發,除了message事件之外它還有另外2個事件open和error,open事件在建立連接的時候觸發,error事件在無法建立連接的時候觸發。
Web Sockets
Web Sockets是一種與服務器進行全雙工雙向通信的通道。Web Sockets不適用HTTP協議,而前面說的Ajax和Comet都是使用HTTP協議。篇幅關系本文對Web Sockets不作討論。
總結
Ajax實現在不加載頁面的情況下向服務器請求數據,提升網頁的用戶體驗。實現Ajax技術的XHR會遇到跨域安全策略的限制,通過CORS解決跨域問題需要瀏覽器和服務器兩端的配合。JSONP是一種實現跨域訪問的”小技巧“但也是存在一些問題。Comet對Ajax進行了拓展,讓服務器能夠實時向瀏覽器推送數據,但從實現來看不管是輪詢還是HTTP流,都是瀏覽器先向服務器發起請求連接。Web Sockets的全雙工雙向通信也有其特色,以后有時間可以繼續了解。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。