終於明白如何去寫原生AJAX

面試常問的題----手寫原生AJAX。 如下是我的的概括總結,但願對你們有幫助。javascript


一)原生JavaScript寫出AJAX

首先咱們根據文檔進行相應的步驟分析。 第一步:建立對象 第二步:初始化 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獲取完整的迴應數據

記住這張圖

ajax思惟導圖 (2).jpg

一、建立對象

IE五、6不兼容XMLHttpRequest,因此要使用ActiveXObject()對象,並傳入 'Microsoft.XMLHTTP',達到兼容目的。

var xhq = null
    if (XMLHttpRequest) {
        xhq = new XMLHttpRequest() // 建立對象
    } else {
        xhq = new ActiveXObject("Microsoft.XMLHTTP") // 兼容IE五、6
    }
複製代碼

二、初始化 HTTP 請求參數

語法: 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文檔

相關文章
相關標籤/搜索