用原生js封裝一個ajax請求方法

袁小巨集發表於2018-11-21

實現功能

  • 可以實現常用的get/post請求
  • 支援text/json/xml幾種返回資料型別
  • 返回的是一個Promise物件

引數:options

  • url: 請求地址
  • dataType: 資料格式,text/json/xml,預設text,不區分大小寫
  • method: 請求方式,預設get,不區分大小寫
  • data: 請求引數,oject型別

注意:get請求若需帶引數,引數仍丟入data屬性,自動拼接url

測試:

  • 寫了兩個簡單的php程式測試了post和get請求
  • 請求了4種不同型別資料的本地檔案,包括:陣列、物件、文字、xml

不足之處

  • 除常用的post/get請求外,其他請求方式不熟悉,沒測試過,可能會不適用
  • 方法返回的是Promise物件,不是最終結果(以後有空再琢磨)

程式碼

ajax程式碼

這段程式碼是封裝的方法主體,注意的是,請求方法返回的是Promise物件。

myAjax.js

/**
 * ajax請求
 * @description 自己寫的ajax請求
 * @param {Object} options 請求配置資訊
 * @param {String} options.url 請求地址
 * @param {String} options.dataType 資料格式 json/text/xml
 * @param {String} options.method 請求方式,預設get
 * @param {Object} options.data 請求引數,json格式
 * [options={url, dataType, method}]
 * @returns {Object} 返回一個Promise物件
 */
function myAjax(options) {
    function transformData(object){
        let oStr = '';
        for(var key in object){
            oStr += key+"="+object[key]+"&";
        };
        return oStr.slice(0,-1);
    };
    return new Promise(function (resolve, reject) {
        let method = options.method ? options.method.toUpperCase() : 'GET';
        let xhr = new XMLHttpRequest();//建立請求物件
        if (method === 'POST') {
            xhr.open(method, options.url);//連線伺服器
            xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");//post請求新增請求頭
            xhr.send(transformData(options.data));//傳送請求,帶處理過的引數
        } else if(method === 'GET') {
            let url = options.data ? options.url + '?' + transformData(options.data) : options.url;
            xhr.open(method, url);//get請求url需要拼接引數
            xhr.send();
        } else {//其他請求方式
            xhr.open(method, options.url);
            xhr.send();
        };
        //接收返回結果
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (
                    (xhr.status >= 200 && xhr.status < 300) ||
                    xhr.status === 304
                ) {
                    let dataType = options.dataType || 'TEXT',
                        data = null;
                    switch (dataType.toUpperCase()) {
                        case 'JSON':
                            data = JSON.parse(xhr.responseText);
                            break;
                        case 'TEXT':
                            data = xhr.responseText;
                            break;
                        case 'XML':
                            data = xhr.responseXML;
                            break;
                    };
                    resolve(data);
                } else {
                    reject({
                        statusCode: xhr.status,
                        msg: '請求錯誤'
                    });
                }
            };
        }
    });
};
複製程式碼

測試程式碼

分別測試了get/post請求,用兩個Promise.all獲取最終的結果。

測試的檔案和php程式碼,感興趣可以到我的github獲取一下

//測試用例

//post請求
let ajax_post = myAjax({url:'program/test_post.php', method:'POST', dataType: 'json', data: {name:'ysh',age:23}});
//get請求
let ajax_get = myAjax({url:'program/test_get.php', method:'GET', dataType: 'json', data: {name:'ysh',age:23}});
Promise.all([ajax_post, ajax_get]).then(res => {
    console.log(res);
}).catch( err => {
    console.log('請求出錯了', err);
});

//資源get請求
let arr = myAjax({url:'data/arr.txt', dataType: 'json'}),
    json = myAjax({url:'data/json.txt', dataType: 'json'}),
    text = myAjax({url:'data/text.txt', dataType:'text'}),
    xml = myAjax({url:'data/xmlData.xml', dataType:'xml'});
Promise.all([arr, json, text, xml]).then(res => {
    console.log(res);
}).catch(err => {
    console.log('請求出錯了', err);
});

複製程式碼

結果列印如下圖。 因為是非同步請求,兩個Promise.all結果列印的順序要看他們請求完成的先後來決定。這裡第二個Promise.all的結果反而先列印了,因為我這裡有快取,所以檔案請求比較快,php程式需要處理,稍微慢一些。如果放在真正的公網環境,順序可能會不一樣。

測試結果


以上,就是我自己封裝的一個ajax請求方法,歡迎拍磚。

第一次寫東西,很開心!!

我真棒

相關文章