util-6.http相關(httpUtil)

/**
 * ========================http========================
 */
var httpUtil = {
    /**
     * XMLHttpRequest是一個瀏覽器接口,使得Javascript可以進行HTTP(S)通信,這就是我們熟悉的AJAX。
     * xhr.readyState:XMLHttpRequest對象的狀態,等於4表示數據已經接收完畢。
     * xhr.status:服務器返回的狀態碼,等於200表示一切正常。
     * xhr.responseText:服務器返回的文本數據
     * xhr.responseXML:服務器返回的XML格式的數據
     * xhr.statusText:服務器返回的狀態文本。
     * @returns {boolean}
     * @constructor
     */
    "XMLHttpRequest": function(){
        var xhr = null;
        if(window.XMLHttpRequest){ //非IE瀏覽器&IE6+
            xhr = new XMLHttpRequest();
        }else if(window.ActiveXObject){  //IE瀏覽器:IE5&IE6
            xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }else{
            alert("Your browser does not support XMLHTTP.");
            return false;
        }
        var fileurl = "/..."; //資源請求路徑(包含js文件內聯實現,或者接口路徑等)
        xhr.open("GET",fileurl,true);  //第三個參數爲async是否爲異步,默認爲true
        //監聽請求完成事件
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4 ){ //四個狀態: 1.uninitialized 未初始化  2.loading 加載中  3.loaded 加載完成  4.complete 完成
                if(xhr.status>=200&&xhr.status<300 || xhr.status==304){ //200<=狀態碼<300爲有效請求,304爲緩存中獲取
                    var responsetext = xhr.responseText; //服務器返回的文本數據
                }else{
                    alert(xhr.statusText); //服務器返回的狀態文本
                }
            }
        };

        var formData = new FormData();
        formData.append('tel', '18217767969');
        formData.append('psw', '111111');
        xhr.send(formData);  //發送請求內容,沒內容時,傳值爲null
    }
}

/**
 * http.js start
 * @type {{request: http.request, addAuthorizationHeader: http.addAuthorizationHeader, post: http.post, postBody: http.postBody, get: http.get, getQueryString: (function(*=): string), ajax: http.ajax, delete: http.delete, getUrlParam: http.getUrlParam, getQueryData: http.getQueryData}}
 */
const http = {
    /**
     * js封裝ajax請求
     * >>使用new XMLHttpRequest 創建請求對象,所以不考慮低端IE瀏覽器(IE6及以下不支持XMLHttpRequest)
     * >>使用es6語法,如果需要在正式環境使用,則可以用babel轉換爲es5語法 https://babeljs.cn/docs/setup/#installation
     *
     * @param settings 請求參數模仿jQuery ajax
     * 調用該方法,data參數需要和請求頭Content-Type對應
     *  Content-Type                        data                                     描述
     *  application/x-www-form-urlencoded   'name=哈哈&age=12'或{name:'哈哈',age:12}  查詢字符串,用&分割
     *  application/json                     name=哈哈&age=12'                        json字符串
     *  multipart/form-data                  new FormData()                           FormData對象,當爲FormData類型,不要手動設置Content-Type
     *  注意:請求參數如果包含日期類型.是否能請求成功需要後臺接口配合
     */
    "ajax": (settings = {}) => {
        // 初始化請求參數
        let _s = Object.assign({
            url: '', // string
            type: 'GET', // string 'GET' 'POST' 'DELETE'
            dataType: 'json', // string 期望的返回數據類型:'json' 'text' 'document' ...
            async: true, //  boolean true:異步請求 false:同步請求 required
            data: null, // any 請求參數,data需要和請求頭Content-Type對應
            headers: {}, // object 請求頭
            timeout: 1000, // string 超時時間:0表示不設置超時
            beforeSend: (xhr) => {
            },
            success: (result, status, xhr) => {
            },
            error: (xhr, status, error) => {
            },
            complete: (xhr, status) => {
            }
        }, settings);
        // 參數驗證
        if (!_s.url || !_s.type || !_s.dataType || !_s.async) {
            alert('參數有誤');
            return;
        }
        // 創建XMLHttpRequest請求對象
        let xhr = new XMLHttpRequest();
        // 請求開始回調函數
        xhr.addEventListener('loadstart', e => {
            _s.beforeSend(xhr);
        });
        // 請求成功回調函數
        xhr.addEventListener('load', e => {
            const status = xhr.status;
            if ((status >= 200 && status < 300) || status === 304) {
                let result;
                if (xhr.responseType === 'text') {
                    result = xhr.responseText;
                } else if (xhr.responseType === 'document') {
                    result = xhr.responseXML;
                } else {
                    result = xhr.response;
                }
                // 注意:狀態碼200表示請求發送/接受成功,不表示業務處理成功
                _s.success(result, status, xhr);
            } else {
                _s.error(xhr, status, e);
            }
        });
        // 請求結束
        xhr.addEventListener('loadend', e => {
            _s.complete(xhr, xhr.status);
        });
        // 請求出錯
        xhr.addEventListener('error', e => {
            _s.error(xhr, xhr.status, e);
        });
        // 請求超時
        xhr.addEventListener('timeout', e => {
            _s.error(xhr, 408, e);
        });
        let useUrlParam = false;
        let sType = _s.type.toUpperCase();
        // 如果是"簡單"請求,則把data參數組裝在url上
        if (sType === 'GET' || sType === 'DELETE') {
            useUrlParam = true;
            _s.url += http.getUrlParam(_s.url, _s.data);
        }
        // 初始化請求
        xhr.open(_s.type, _s.url, _s.async);
        // 設置期望的返回數據類型
        xhr.responseType = _s.dataType;
        // 設置請求頭
        for (const key of Object.keys(_s.headers)) {
            xhr.setRequestHeader(key, _s.headers[key]);
        }
        // 設置超時時間
        if (_s.async && _s.timeout) {
            xhr.timeout = _s.timeout;
        }
        // 發送請求.如果是簡單請求,請求參數應爲null.否則,請求參數類型需要和請求頭Content-Type對應
        xhr.send(useUrlParam ? null : http.getQueryData(_s.data));
    },
    // 把參數data轉爲url查詢參數
    "getUrlParam": (url, data) => {
        if (!data) {
            return '';
        }
        let paramsStr = data instanceof Object ? http.getQueryString(data) : data;
        return (url.indexOf('?') !== -1) ? paramsStr : '?' + paramsStr;
    },
    // 獲取ajax請求參數
    "getQueryData": (data) => {
        if (!data) {
            return null;
        }
        if (typeof data === 'string') {
            return data;
        }
        if (data instanceof FormData) {
            return data;
        }
        return http.getQueryString(data);
    },
    // 把對象轉爲查詢字符串
    "getQueryString": (data) => {
        let paramsArr = [];
        if (data instanceof Object) {
            Object.keys(data).forEach(key => {
                let val = data[key];
                // todo 參數Date類型需要根據後臺api酌情處理
                if (val instanceof Date) {
                    val = dateFormat(val, 'yyyy-MM-dd hh:mm:ss');
                }
                paramsArr.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));
            });
        }
        return paramsArr.join('&');
    },
    /**
     * 根據實際業務情況裝飾 ajax 方法
     * 如:統一異常處理,添加http請求頭,請求展示loading等
     * @param settings
     */
    "request": (settings = {}) => {
        // 統一異常處理函數
        let errorHandle = (xhr, status) => {
            console.log('request error...');
            if (status === 401) {
                console.log('request 沒有權限...');
            }
            if (status === 408) {
                console.log('request timeout');
            }
        };
        // 使用before攔截參數的 beforeSend 回調函數
        settings.beforeSend = (settings.beforeSend || function () {
        }).before(xhr => {
            console.log('request show loading...');
        });
        // 保存參數success回調函數
        let successFn = settings.success;
        // 覆蓋參數success回調函數
        settings.success = (result, status, xhr) => {
            // todo 根據後臺接口api判斷是否請求成功
            if (result && result instanceof Object && result.code !== 1) {
                errorHandle(xhr, status);
            } else {
                console.log('request success');
                successFn && successFn(result, status, xhr);
            }
        };
        // 攔截參數的 error
        settings.error = (settings.error || function () {
        }).before((result, status, xhr) => {
            errorHandle(xhr, status);
        });
        // 攔截參數的 complete
        settings.complete = (settings.complete || function () {
        }).after((xhr, status) => {
            console.log('request hide loading...');
        });
        // 請求添加權限頭,然後調用http.ajax方法
        (http.ajax.before(http.addAuthorizationHeader))(settings);
    },
    // 添加權限請求頭
    "addAuthorizationHeader": (settings) => {
        settings.headers = settings.headers || {};
        const headerKey = 'Authorization'; // todo 權限頭名稱
        // 判斷是否已經存在權限header
        let hasAuthorization = Object.keys(settings.headers).some(key => {
            return key === headerKey;
        });
        if (!hasAuthorization) {
            settings.headers[headerKey] = 'test'; // todo 從緩存中獲取headerKey的值
        }
    },
    "get": (url, data, successCallback, dataType = 'json') => {
        http.request({
            url: url,
            type: 'GET',
            dataType: dataType,
            data: data,
            success: successCallback
        });
    },
    "delete": (url, data, successCallback, dataType = 'json') => {
        http.request({
            url: url,
            type: 'DELETE',
            dataType: dataType,
            data: data,
            success: successCallback
        });
    },
    // 調用此方法,參數data應爲查詢字符串或普通對象
    "post": (url, data, successCallback, dataType = 'json') => {
        http.request({
            url: url,
            type: 'POST',
            dataType: dataType,
            data: data,
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            },
            success: successCallback
        });
    },
    // 調用此方法,參數data應爲json字符串
    "postBody": (url, data, successCallback, dataType = 'json') => {
        http.request({
            url: url,
            type: 'POST',
            dataType: dataType,
            data: data,
            headers: {
                'Content-Type': 'application/json; charset=UTF-8'
            },
            success: successCallback
        });
    }
};

Function.prototype.before = function (beforeFn) { // eslint-disable-line
    let _self = this;
    return function () {
        beforeFn.apply(this, arguments);
        _self.apply(this, arguments);
    };
};

Function.prototype.after = function (afterFn) { // eslint-disable-line
    let _self = this;
    return function () {
        _self.apply(this, arguments);
        afterFn.apply(this, arguments);
    };
};

// 日期格式化
const dateFormat = (date, sFormat = 'yyyy-MM-dd') => {
    if (!(date instanceof Date)) {
        return;
    }
    let time = {
        Year: 0,
        TYear: '0',
        Month: 0,
        TMonth: '0',
        Day: 0,
        TDay: '0',
        Hour: 0,
        THour: '0',
        hour: 0,
        Thour: '0',
        Minute: 0,
        TMinute: '0',
        Second: 0,
        TSecond: '0',
        Millisecond: 0
    };
    time.Year = date.getFullYear();
    time.TYear = String(time.Year).substr(2);
    time.Month = date.getMonth() + 1;
    time.TMonth = time.Month < 10 ? '0' + time.Month : String(time.Month);
    time.Day = date.getDate();
    time.TDay = time.Day < 10 ? '0' + time.Day : String(time.Day);
    time.Hour = date.getHours();
    time.THour = time.Hour < 10 ? '0' + time.Hour : String(time.Hour);
    time.hour = time.Hour < 13 ? time.Hour : time.Hour - 12;
    time.Thour = time.hour < 10 ? '0' + time.hour : String(time.hour);
    time.Minute = date.getMinutes();
    time.TMinute = time.Minute < 10 ? '0' + time.Minute : String(time.Minute);
    time.Second = date.getSeconds();
    time.TSecond = time.Second < 10 ? '0' + time.Second : String(time.Second);
    time.Millisecond = date.getMilliseconds();

    return sFormat.replace(/yyyy/ig, String(time.Year))
        .replace(/yyy/ig, String(time.Year))
        .replace(/yy/ig, time.TYear)
        .replace(/y/ig, time.TYear)
        .replace(/MM/g, time.TMonth)
        .replace(/M/g, String(time.Month))
        .replace(/dd/ig, time.TDay)
        .replace(/d/ig, String(time.Day))
        .replace(/HH/g, time.THour)
        .replace(/H/g, String(time.Hour))
        .replace(/hh/g, time.Thour)
        .replace(/h/g, String(time.hour))
        .replace(/mm/g, time.TMinute)
        .replace(/m/g, String(time.Minute))
        .replace(/ss/ig, time.TSecond)
        .replace(/s/ig, String(time.Second))
        .replace(/fff/ig, String(time.Millisecond));
};
/**
 * http.js end
 */

/**
 * 調用頁面代碼 s
 */

/*
<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <div id="buttons">
    <button id="get">get</button>
    <button id="get_dataParam">get_dataParam</button>
    <button id="get_timeout">get_timeout</button>
    <button id="get_document">get_document</button>
    <button id="get_exception">get_exception</button>
    <button id="post_dataParam">post_dataParam</button>
    <button id="post_formDataParam">post_formDataParam</button>
    <button id="post_body">post_body</button>
    <button id="post_body_list">post_body_list</button>
    </div>
    <br>
    <div>
    <label for="file">選擇文件,可多選:</label>
<input id="file" type="file" multiple>
<button id="upload">upload</button>
    </div>
    <br>
    <div>
    <label for="file">文件分塊傳輸:</label>
<input id="bidFile" type="file">
    <button id="uploadFile">uploadFile</button>
    </div>
    <script src="http.js"></script>
    <script>
    document.getElementById('buttons').addEventListener('click', function (e) {
        let url = 'http://88.128.18.144:8081/api/v1/test/';
        const id = e.target.id;
        if (id === 'get') {
            url = url + id;
            fetch(url + '?name=哈哈&age=12').then(res => res.json()).then(data => {
                console.log(data);
            });
        }
        if (id === 'get_dataParam') {
            http.request({
                url: url + id,
                data: {name: '哈哈', age: 12}, //data: 'name=哈哈&age=12',
                success: function (result, status, xhr) {
                    console.log(result, '\n status:', status, xhr);
                    debugger;
                }
            });
        }
        if (id === 'get_timeout') {
            http.request({
                url: url + id,
                timeout: 1000
            });
        }
        if (id === 'get_document') {
            // http.request是針對這個api(http://88.128.18.144:8081/api/)封裝的,這裏請求另外一個接口,不能使用http.request
            http.ajax({
                url: 'http://172.16.19.136:9000/kit_file_server/',
                dataType: 'document',
                success: function (result, status, xhr) {
                    console.log(result, '\n status:', status, xhr);
                    debugger;
                }
            });
        }
        if (id === 'get_exception') {
            http.get(url + id);
        }
        if (id === 'post_dataParam') {
            url = url + id;
            http.post(url, {name: '哈哈', age: 12}, (result, status, xhr) => {
                console.log('進行業務操作');
            })
        }
        if (id === 'post_formDataParam') {
            // 傳FormData類型參數,不要設置contentType,瀏覽器會自動設置contentType爲'multipart/form-data'
            let formData = new FormData();
            formData.append('name', '哈哈');
            formData.append('age', '123');
            http.request({
                url: url + id,
                type: 'POST',
                data: formData,
                success: function (result, status, xhr) {
                    console.log('進行業務操作');
                }
            });
        }
        if (id === 'post_body') {
            url = url + id;
            http.postBody(url, JSON.stringify({
                name: '哈哈',
                age: 12,
                birthday: dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'),
                hobbies: ['a', 'b', 'c']
            }), (result, status, xhr) => {
                console.log('進行業務操作');
            });
        }
        if (id === 'post_body_list') {
            url = url + id;
            http.postBody(url, JSON.stringify(['a', 'b', 'c']), (result, status, xhr) => {
                console.log('進行業務操作');
            });
        }
    });
document.getElementById('upload').addEventListener('click', function () {
    let files = document.getElementById('file').files;
    if (files.length === 0) {
        console.log('沒有選擇文件');
        return;
    }
    let form = new FormData(); // FormData 對象
    Array.from(files).forEach((file, index) => {
        form.append(index, file); // 文件對象
    });
    http.ajax({
        url: 'http://88.128.18.144:3333/upload?directory=test',
        type: 'POST',
        data: form,
        success: function (result, status, xhr) {
            console.log('文件上傳成功', result.data);
        }
    });
});
const LENGTH = 1024 * 100; // 100kb
document.getElementById('uploadFile').addEventListener('click', function () {
    let file = document.getElementById('bidFile').files[0];
    if (!file) {
        console.log('沒有選擇文件');
        return;
    }
    let start = 0, end = LENGTH;
    while (start < file.size) {
        let blob = file.slice(start, end);
        let form = new FormData();
        form.append('blob', blob);
        http.ajax({
            url: 'http://88.128.18.144:3333/upload?directory=test',
            type: 'POST',
            data: form,
            success: function (result, status, xhr) {
                console.log('文件分塊上傳', result.data);
            }
        });
        start = end;
        end = start + LENGTH;
    }
});
</script>
</body>
</html>
*/
/**
 * 調用頁面代碼 e
 */

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章