AJAX 是 Asynchronous JavaScript And XML 的簡稱,它可以讓頁面在不重新整理的情況下從伺服器獲取資料。
XMLHttpRequest
瀏覽器使用XMLHttpRequest
物件於伺服器通訊,它可以使用JSON,XML,HTML和text等格式傳送和接收資料。
低版本 IE 瀏覽器沒有XMLHttpRequest
物件,但是它可以使用ActiveXObject
物件代替。
if (window.XMLHttpRequest) { // IE7+
XHR = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6
XHR = new ActiveXObject("Microsoft.XMLHTTP");
}
複製程式碼
建立 XHR 例項過後就可以監聽該例項的狀態改變事件onreadystatechange
,它會在 XHR 例項的readyState
的值改變時觸發回撥函式。
XHR.onreadystatechange = function () { }
複製程式碼
然後我們就可以使用open
方法初始化一個請求和send
方法傳送 HTTP 請求。
XHR.open('GET', 'http://q.com')
// open 方法一共有 5 個引數,method, url, async, user, password 後三個可選。
// async 表示這次是否非同步請求,預設是 true
XHR.send()
// send 方法接受一個可選引數 請求主體。
// 引數可以是 FormData, FormData, ArrayBuffer, Document, 序列化字串
複製程式碼
如果是post
方法,就要在send
之前設定請求頭的Content-Type
。
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 它接受兩個引數 header 和 value
複製程式碼
然後我們就要處理伺服器返回的資料,回到onreadystatechange
函式。它監聽readyState
屬性的變化,而它一共有 5 個值。
0
表示 請求還未初始化,尚未呼叫 open() 方法。1
表示 已建立伺服器連結,open() 方法已經被呼叫。2
表示 請求已接受,send() 方法已經被呼叫,並且頭部和狀態已經可獲得。3
表示 正在處理請求,下載中; responseText 屬性已經包含部分資料。4
表示 完成,下載操作已完成。
我們還需要關心status
屬性它也是隻讀屬性,它是這次響應中的 HTTP 數字狀態碼。在請求之前和 XMLHttpRequest 出錯時它為0
。
responseText
屬性是實際的資料,它是字串,如果相應是 JSON 格式,需要用 JSON 的 parse 處理。
XHR.onreadystatechange = function () {
if (XHR.readyState === 4 && XHR.status === 200) {
console.log(JSON.parse(XHR.responseText))
}
}
複製程式碼
如果伺服器返回的是 XML, 我們可以用responseXML
屬性獲得資料。
// 如果已指明,responseType 必須是空字串或 "docuemnt"
XHR.responseType = 'document';
// overrideMimeType() 用來強制解析 response 為 XML
XHR.overrideMimeType('text/xml');
// --------------
var root = XHR.responseXML.getElementsByTagName('root').item(0)
複製程式碼
responseType
屬性是一個列舉型別的屬性,返回響應資料的型別。
withCredentials
屬性是一個Boolean型別,它指示了是否該使用類似cookies,authorization headers(頭部授權)或者TLS客戶端證照這一類資格證照來建立一個跨站點訪問控制請求。
(在IE中,超時屬性可能只能在呼叫 open() 方法之後且在呼叫 send() 方法之前設定)
abort
方法用來終止請求
getAllResponseHeaders
方法返回所有的響應頭
getResponseHeader(name)
方法返回包含指定頭文字的字串
XMLHttpRequset 2
XMLHttpRequset 2 增加了一些新功能。比如能傳送FormData
。
超時時間
timeout
屬性是超時時間,單位毫秒。當超時發生時他會觸發ontimeout
回撥函式。
xhr.open('GET', '/server')
xhr.timeout = 2000
xhr.ontimeout = function (e) {}
xhr.send(null);
複製程式碼
還有 6 個進度事件。
loadstart
在收到響應的第一個位元組觸發progress
在接收期間不斷觸發error
發生錯誤abort
呼叫abort方法而終止load
接收到完整資料loadend
在通訊完成或abort error load事件後觸發
有load
事件就不用readystatechange
事件和讀取readyState
屬性。
xhr.addEventListener("progress", updateProgress, false);
xhr.addEventListener("load", transferComplete, false);
xhr.addEventListener("error", transferFailed, false);
xhr.addEventListener("abort", transferCanceled, false);
function updateProgress(event) {
if (event.lengthComputable) {
console.log(`${event.position} / ${event.totalSize}`)
}
}
複製程式碼
其中progress
的事件物件多了三個屬性。
lengthComputable
布林值 表示進度資訊是否可用position
已經接收到的位元組數totalSize
根據Content-Length預期的位元組數
跨域
同源策略限制了從同一個源載入的文件或指令碼如何與來自另一個源的資源進行互動。這是一個用於隔離潛在惡意檔案的重要安全機制。
當前網址(http://news.a.com)和請求網址
https://news.a.com
不同協議http://news.a.com:8080
不同埠http://home.a.com
不同域名
時就不是同源。
為了使 ajax 可以從不同的網址獲取資料。
我們可以使用跨域資源共享(CORS)來解決問題。
在傳送請求時會有個Origin
頭表示請求頁面的源資訊,
如果伺服器返回的Access-Control-Allow-Origin
中有相同的源資訊或是*
那麼就可以跨域請求資訊,請求和響應都不包含cookie
。
CORS通過Preflighted Requests
透明伺服器驗證機制支援使用自定義頭部、get和post之外的方法,不同型別的主題內容。
這種請求已OPTIONS方法傳送,下面是它傳送的頭資訊:
Origin
源
Access-Control-Request-Method
請求自身使用的方法
Access-Control-Request-Headers
自定義頭部資訊,用逗號分隔
傳送請求後,伺服器來決定是否允許,伺服器會傳送如下資訊與瀏覽器溝通:
Access-Control-Allow-Origin
允許的源
Access-Control-Allow-Methods
允許的方法,逗號分隔
Access-Control-Allow-Headers
允許的頭部,逗號分隔
Access-Control-Allow-Max-Age
Preflight請求快取的時間(秒)
預設情況下跨域不提供cookie、HTTP認證、SSL證明,通過withCredentials
屬性設定為true
可以指定某個請求因該傳送憑據。
伺服器如果接收請求會返回Access-Control-Allow-Credentials
為true
的頭資訊。
還有一種方法是使用JSONP
。
jsonp
方法主要是建立script
標籤來獲得資料,一般通過請求後面跟?callback=fn
回掉函式來獲取資料。
Fetch
Fetch 是網路請求的一個更好的替代方法。相比於 XMLHttpRequest,Fetch 寫法更簡單,功能更強大。
fetch('http://a.com')
.then(function(response) {
if (response.ok) {
return response.json();
}
throw new Error('err')
})
.then(function(myJson) {
console.log(myJson);
})
.catch(err => {
console.log(err)
})
複製程式碼
fetch 函式接受兩個引數,返回一個 Promise 物件 。
第一個引數是 URL 或 Request 物件。第二個引數是可選一個配置項物件。
{
method: 'GET', // 請求方法
headers: {
'user-agent': 'Mozilla/4.0 MDN Example',
'content-type': 'application/json'
}, // 頭資訊
body: JSON.stringify({data: 1}), // 請求的 body 資訊,Blob, FormData 等
mode: 'cors', // 請求的模式,cors、 no-cors 或 same-origin
credentials: 'include', // omit、same-origin 或 include。為了在當前域名內自動傳送 cookie, 必須提供這個選項
cache: 'no-cache', // default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached
redirect: 'follow', // 可用的 redirect 模式: follow (自動重定向), error (如果產生重定向將自動終止並且丟擲一個錯誤), 或者 manual (手動處理重定向).
referrer: 'no-referrer', // no-referrer、client或一個 URL。預設是 client。
referrerPolicy: 'no-referrer', // 指定 referer HTTP頭
integrity: 'sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=', // 包括請求的 subresource integrity 值
}
複製程式碼
then 的回撥函式接受一個 Response 物件。Response 實現了 Body(代表響應/請求的正文,允許你宣告其內容型別是什麼以及應該如何處理。)
它有 9 個屬性。
type
只讀 包含Response的型別 (例如, basic, cors)url
只讀 包含Response的URLuseFinalURL
包含了一個布林值來標示這是否是該Response的最終URLstatus
只讀 包含Response的狀態碼ok
只讀 包含了一個布林值來標示該Response成功(狀態碼200-299)edirected
只讀 表示該Response是否來自一個重定向,如果是的話,它的URL列表將會有多個statusText
只讀 包含了與該Response狀態碼一致的狀態資訊headers
只讀 包含此Response所關聯的Headers 物件bodyUsed
Body 只讀 包含了一個布林值來標示該Response是否讀取過Body
8 個方法
clone
建立一個Response物件的克隆error
返回一個繫結了網路錯誤的新的Response物件redirect(url, status)
用另一個URL建立一個新的 response
Body(都返回一個 Promise 例項)
arrayBuffer
接受一個 Response 流, 並等待其讀取完成. 並 resolve 一個 ArrayBuffer 物件blob
blob()方法使用一個 Response 流,並將其讀取完成formData
將 Response 物件中的所承載的資料流讀取並封裝成為一個物件json
使用一個 Response 流,並將其讀取完成。解析結果是將文字體解析為 JSONtext
提供了一個可供讀取的"返回流", 它返回一個包含USVString物件,編碼為UTF-8
WebSocket
WebSockets 是一種先進的技術。它可以在使用者的瀏覽器和伺服器之間開啟雙工、雙向通訊會話。
WebSocket 建構函式,接受兩個引數,url 和 protocols(可選)。
url 以 ws://
或 wss://
(加密)開頭
protocols 是 單協議字串或者包含協議字串的陣列。這些字串用於指定子協議,這樣單個伺服器可以實現多個WebSocket子協議(例如,您可能希望一臺伺服器能夠根據指定的協議處理不同型別的互動)protocol)。如果不指定協議字串,則假定為空字串。
var s = new WebSocket('ws://www.a.com/s.php') // 必須傳入絕對URL,可以是任何網站
s.readyState // 0 建立連線 1 已經建立 2 正在關閉 3 連線已關閉或者沒有連結成功
s.send('hello') // 傳送的資料必須是純文字
s.onopen = function (){
console.log('成功建立連線時觸發')
}
s.onerror = function () {
console.log('發生錯誤,連線不能持續時')
}
s.onmessage = function (event) { // 當接收到訊息時
console.log(event.data) // 資料是純字元
}
s.close() // 關閉連線
s.onclose = function (event) {
/*
* event.wasClean 是否明確的關閉
* event.code 伺服器返回的數值狀態碼
* event.reason 字串,伺服器返回的訊息
*/
console.log('連線關閉時')
}
複製程式碼
一共有 10 個屬性
binaryType
返回websocket連線所傳輸二進位制資料的型別(blob, arraybuffer)bufferedAmount
只讀 返回已經被send()方法放入佇列中但還沒有被髮送到網路中的資料的位元組數。一旦佇列中的所有資料被髮送至網路,則該屬性值將被重置為0。但是,若在傳送過程中連線被關閉,則屬性值不會重置為0。extensions
只讀 返回伺服器選擇的副檔名。這當前只是空字串或連線協商的擴充套件列表onclose
用於指定連線失敗後的回撥函式onmessage
用於指定當從伺服器接受到資訊時的回撥函式onopen
用於指定連線成功後的回撥函式protocol
只讀 伺服器選擇的下屬協議readyState
只讀 當前的連結狀態url
只讀 WebSocket 的絕對路徑
2 個方法
close(code, reason)
數字狀態碼 可選 預設 1005和一個可選的類可讀的字串,它解釋了連線關閉的原因。send(data)
向伺服器傳送資料(ArrayBuffer,Blob等)