面試常問的題----手寫原生AJAX。 如下是我的的概括總結,但願對你們有幫助。javascript
首先咱們根據文檔進行相應的步驟分析。 第一步:建立對象 第二步:初始化 HTTP 請求參數 第三步:發送請求 第四步:監聽請求狀態,執行對應回調函數java
onreadystatechange 每次狀態改變所觸發事件的事件。面試
responseText 從服務器接收到的響應體(不包括頭部),或者若是尚未接收到數據的話,就是空字符串。ajax
responseXML 對請求的響應,解析爲 XML 並做爲 Document 對象返回。服務器
status 從服務器返回的數字代碼,好比常見的404(未找到)和200(已就緒)app
status Text 請求的 HTTP 的狀態代碼dom
readyState HTTP 請求的狀態.當一個 XMLHttpRequest 初次建立時,這個屬性的值從 0 開始,直到接收到完整的 HTTP 響應,這個值增長到 4。異步
0 (未初始化) 對象已創建,可是還沒有初始化(還沒有調用open方法)async
1 (初始化) 對象已創建,還沒有調用send方法函數
2 (發送數據) send方法已調用,可是當前的狀態及http頭未知
3 (數據傳送中) 已接收部分數據,由於響應及http頭不全,這時經過responseBody和responseText獲取部分數據會出現錯誤
4 (完成) 數據接收完畢,此時能夠經過responseXml和responseText獲取完整的迴應數據
IE五、6不兼容XMLHttpRequest,因此要使用ActiveXObject()對象,並傳入 'Microsoft.XMLHTTP',達到兼容目的。
var xhq = null
if (XMLHttpRequest) {
xhq = new XMLHttpRequest() // 建立對象
} else {
xhq = new ActiveXObject("Microsoft.XMLHTTP") // 兼容IE五、6
}
複製代碼
語法: open(method, url, async, username, password) 參數說明: 必填 method 請求的類型 值包括 GET、POST 和 HEAD 必填 url 請求的路徑 須要向服務器請求的路徑 可選 async 這次請求的方式 默認爲true 即爲異步 可選 username 與 password 這次請求須要的身份驗證
同時該請求會將 readyState 設置爲1,並把 responseText、responseXML、status 以及 statusText 參數設置爲它們的默認值。
xhq.open('get', 'https://www.easy-mock.com/mock/5cf7654cf8ab93502742fb99/example/query', true)
複製代碼
此處接口使用easy-mock模擬。
語法: send(body) 參數說明: 可選 傳遞的參數列表
xhq.send({
username: '123'
})
複製代碼
請求發送後, send()會把 readyState 設置爲 2,並觸發 onreadystatechange 事件。
當全部的 HTTP 響應頭部已經接收,send() 或後臺線程把 readyState 設置爲 3 並觸發 onreadystatechange 事件。
當響應完成,send() 或後臺線程把 readyState 設置爲 4,並最後一次觸發事件。
當readyState爲4時,且服務器響應爲200時
xhq.onreadystatechange = function () {
if ( xhq.readystate == 4 && xhq.status == 200 ) {
// success 回調
success(xhq.responseText)
} else if (xhq.readyState == 4 && xhq.status !== 200) {
// error 回調
error()
}
}
複製代碼
function sendAjax(obj) {
// get方式傳入時,將內容進行data內容進行拼接
function splicStr(data) {
var str = ''
for (var i in data) {
str = i + '=' + data[i]
}
return str
}
// 原生ajax實現 步驟分析
// 1、聲明XMLHttpRequest, 爲了兼容IE五、6須要使用ActiveXObject()
var xhq = null
if (XMLHttpRequest) {
xhq = new XMLHttpRequest() // 建立對象
} else {
xhq = new ActiveXObject("Microsoft.XMLHTTP") // 兼容IE五、6
}
// 2、初始化HTTP請求參數, 只初始化並不會發送
if (obj.method.toUpperCase() === 'GET') { // get方法
xhq.open(obj.method, obj.url + '?' + splicStr(obj.data), typeof obj.async === 'boolean'? obj.async : true) // 路徑拼接
// 3、發送這次請求
xhq.send()
}
else if (obj.method.toUpperCase() === 'POST') { // post方法
xhq.open(obj.method, obj.url, typeof obj.async === 'boolean'? obj.async : true)
xhq.setRequestHeader("content-type","application/x-www-form-urlencoded") // 以表單提交
// 3、發送這次請求
xhq.send(obj.data)
}
//4、監聽發送
xhq.onreadystatechange = function () {
if ( xhq.readyState == 4 && xhq.status == 200 ) {
// success 回調
success(xhq.responseText)
} else if (xhq.readyState == 4 && xhq.status !== 200) {
// error 回調
error()
}
}
}
sendAjax({
url: 'your url',
method: 'post',
async: true,
data: {
username: 'xiong',
pwd: '123'
},
success: function (data) {
console.log(data)
},
error: function () {
console.log('發生了錯誤')
}
})
複製代碼
function sendAjax(obj) {
this.xhq = null
this.method = obj.method || 'get'
this.url = obj.url
this.data = obj.data
this.async = typeof obj.async === 'boolean'? obj.async : true
this.success = obj.success
this.error = obj.error
this.init()
}
sendAjax.prototype = {
init: function () {
if (XMLHttpRequest) {
this.xhq = new XMLHttpRequest() // 建立對象
} else {
this.xhq = new ActiveXObject("Microsoft.XMLHTTP") // 兼容IE五、6
}
this.openReq()
this.watchReq()
},
openReq: function () {
if (this.method.toUpperCase() === 'GET') { // get方法
this.xhq.open(this.method, this.url + '?' + this.splicStr(this.data), this.async) // 路徑拼接
// 3、發送這次請求
this.xhq.send()
}
else if (this.method.toUpperCase() === 'POST') { // post方法
this.xhq.open(this.method, this.url, this.async)
this.xhq.setRequestHeader("content-type","application/x-www-form-urlencoded") // 以表單提交
// 3、發送這次請求
this.xhq.send(this.data)
}
},
watchReq: function () {
var that = this
this.xhq.onreadystatechange = function () {
if ( that.xhq.readyState == 4 && that.xhq.status == 200 ) {
// success 回調
that.success(that.xhq.responseText)
} else if (that.xhq.readyState == 4 && that.xhq.status !== 200) {
// error 回調
that.error()
}
}
},
splicStr: function (data) {
var str = ''
for (var i in data) {
str = i + '=' + data[i]
}
return str
}
}
new sendAjax({
url: 'https://www.easy-mock.com/mock/5cf7654cf8ab93502742fb99/example/query',
method: 'get',
async: true,
data: {
username: 'xiong',
pwd: '123'
},
success: function (data) {
console.log(data)
},
error: function () {
console.log('發生了錯誤')
}
})
複製代碼
案例沒有處理全部可能,可是已經夠基本使用。 熊吉祝你們學習愉快。
文章內容借鑑了W3school關於XMLHttpRequest文檔