JavaScript XmlHttpRequest

XmlHttpRequest

   这是原生的一种发送网络请求的技术,存在非常久的方案。

   基本上所有框架对于网络请求的部分都是基于它来做的。

方法介绍

open

   open()用于创建请求(单纯创建,并不发送)

   注意:如果是open()methodGET,则需要自带参数。

参数说明
method 请求方式
url 请求地址
async 是否异步

send

   send()用于发送请求,如果你的open()methodGET,则这里可以填上null

参数说明
body 要发送的数据(字符串类型)
function ajax() {
    let xhr = new XMLHttpRequest();
    xhr.open("GET", "http://127.0.0.1:8000/", true);
    xhr.send(null);

}

setRequestHeader

   用于设置请求头,一般我们会指定编码方式。

参数说明
header 请求头的key(字符串类型)
vlaue 请求头的value(字符串类型)

getAllResponseHeaders

   用于获取响应头,返回所有的响应头数据(字符串类型)。

getResponseHeader

   获取响应头中指定header的值,返回该响应头的数据(字符串类型)。

  

参数描述
header 响应头的key(字符串类型)

abort

   终止请求。

属性介绍

status

   状态码,如200/404等等。

readyState

   这是一个整数类型的状态值,使用XmlHttpRequest时共有5种状态。

状态值描述
0 未初始化,尚未调用open()方法
1 启动,调用了open()方法,未调用send()方法
2 发送,已经调用了send()方法,未接收到响应
3 接收,已经接收到部分响应数据
4 完成,已经接收到全部响应数据

statesText

   状态文本(字符串),如:OK、NotFound...

responseText

   这是服务器返回的数据(字符串类型)

XmlDocument

   XmlDocumentresponseXML一样,都是 服务器返回的数据(Xml对象)

回调函数

onreadystatechange

   当readyState的值改变时自动触发执行其对应的函数(回调函数)

   有了这个回调函数,我们就可以开始做一个原生的ajax了。

使用方式

简单封装

   这下面是一个最简单的封装。

    function ajax() {

        let xhr = new XMLHttpRequest();
        xhr.open("GET", "http://127.0.0.1:8000/?username=Yunya", true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
        xhr.send(null);
        // 如果是POST请求,则 数据格式为 xhr.send('n1=1;n2=2;');


        xhr.onreadystatechange = function(){
            console.log(xhr.status);
            if (xhr.readyState == 4 && xhr.status==200){
                console.log("请求成功");
                console.log(xhr.responseText);
            }
            else if(xhr.status == 404){
                console.log("请求失败");
            }
            else if(xhr.status == 500){
                console.log("服务器内部错误")
            }
        }
    }

初级封装

   下面是融合了POSTGET的封装,基本使用与jQueryajax相同

(function () {

    class Ajax {

        constructor({ url, type, dataType, data, contentType, success, error }) {
            this.url = url;
            this.type = type;
            this.data = data;
            this.contentType = !!contentType == true ? contentType : 'application/x-www-form-urlencoded';
            this.success = typeof success == "function" ? success : (res) => { };
            this.error = typeof error == "function" ? error : (res) => { };
            this.xhr = null;
            this.send_data = null;
            this.init();
        }

        init() {
            // 第一步,处理上传的数据格式
            this.dataFormat();
            // 第二步:如果是GET提交,则send()中不能有任何数据
            if (this.type == "GET") {
                this.getAjax();
            } else if (this.type == "POST") {
                this.postAjax();
            }
            // 第三步:判断后端返回信息
            this.callbackAjax();
        }

        dataFormat() {
            this.send_data = Object.entries(this.data).reduce((prev, value, index, array) => {
                if (array.length - 1 == index) {
                    return prev += `${value[0]}=${value[1]}`
                }
                else {
                    return prev += `${value[0]}=${value[1]}&`
                }

            }, "")

        }

        getAjax() {
            this.url = this.url.concat('?', this.send_data,);
            this.xhr = new XMLHttpRequest();
            this.xhr.open(this.type, this.url, true);
            this.xhr.setRequestHeader("Content-Type", this.contentType)
            this.xhr.send(null);


        }

        postAjax() {
            this.xhr = new XMLHttpRequest();
            this.xhr.open(this.type, this.url, true);
            this.xhr.setRequestHeader("Content-Type", this.contentType)
            this.xhr.send(this.send_data);

        }


        callbackAjax() {
            this.xhr.onreadystatechange = () => {
                if (this.xhr.readyState == 4 && this.xhr.status == 200) {
                    if (this.dataType == "JSON") {
                        this.success(JSON.parse(this.xhr.responseText));
                    } else {
                        this.success(this.xhr.responseText);
                    }

                } else if (this.xhr.status == 404) {
                    this.error("请求失败,检查IP与PORT");
                } else if (this.xhr.status == 500) {
                    this.error("请求失败,服务器内部错误");
                }
            }

        }


    }
    window.Ajax = Ajax;
}())

// 调用方式 new Ajax() 传入参数即可

文件上传

   由于上面不支持文件上传,所以我们需要再做一个有文件上传功能的AJAX

(function () {

    class Ajax {

        constructor({ url, type, dataType, data, contentType, success, error,file=false }) {
            this.url = url;
            this.type = type;
            this.data = data;
            this.contentType = !!contentType == true ? contentType : 'application/x-www-form-urlencoded';
            this.success = typeof success == "function" ? success : (res) => { };
            this.error = typeof error == "function" ? error : (res) => { };
            this.xhr = null;
            this.send_data = null;
            this.file = file; // 是否支持文件上传
            this.init();
        }

        init() {
            // 第一步,处理上传的数据格式

            this.dataFormat();

            // 第二步:如果是GET提交,则send()中不能有任何数据
            if (this.type == "GET") {
                this.getAjax();
            }else if (this.file){
                this.fileAjax();
            }
            else if (this.type == "POST") {
                this.postAjax();
            }
            // 第三步:判断后端返回信息
            this.callbackAjax();
        }

        dataFormat() {
            this.send_data = Object.entries(this.data).reduce((prev, value, index, array) => {
                if (array.length - 1 == index) {
                    return prev += `${value[0]}=${value[1]}`
                }
                else {
                    return prev += `${value[0]}=${value[1]}&`
                }

            }, "")

        }

        getAjax() {
            this.url = this.url.concat('?', this.send_data,);
            this.xhr = new XMLHttpRequest();
            this.xhr.open(this.type, this.url, true);
            this.xhr.setRequestHeader("Content-Type", this.contentType);
            this.xhr.send(null);


        }

        postAjax() {
            this.xhr = new XMLHttpRequest();
            this.xhr.open(this.type, this.url, true);
            this.xhr.setRequestHeader("Content-Type", this.contentType);
            this.xhr.send(this.send_data);

        }

        fileAjax(){
            // 注意,文件上传只能是POST形式
            this.xhr = new XMLHttpRequest();
            this.xhr.open("POST", this.url,true);
            this.xhr.send(this.data);  // 注意,这里是上传的this.data
        }


        callbackAjax() {
            this.xhr.onreadystatechange = () => {
                if (this.xhr.readyState == 4 && this.xhr.status == 200) {
                    if (this.dataType == "JSON") {
                        this.success(JSON.parse(this.xhr.responseText));
                    } else {
                        this.success(this.xhr.responseText);
                    }

                } else if (this.xhr.status == 404) {
                    this.error("请求失败,检查IP与PORT");
                } else if (this.xhr.status == 500) {
                    this.error("请求失败,服务器内部错误");
                }
            }

        }


    }
    window.Ajax = Ajax;
}())

json格式

   如果需要发送JSON格式的数据,则我们还需要进行改进。

   首先要明确,GET提交方式不要使用JSON格式的数据进行发送。

   如果你后端是使用Django的话,那么json格式不会存放进request.POST中,而是存放request.body中。

   说明:filetrue时,代表上传文件,json_datatrue时,代表前端发送json数据至后端,dataTypeJSON时,代表自动转换后端传过来的json格式数据。

(function () {

    class Ajax {

        constructor({ url, type, dataType, data, contentType, success, error,file=false,json_data=false }) {
            this.url = url;
            this.type = type;
            this.data = data;
            this.contentType = !!contentType == true ? contentType : 'application/x-www-form-urlencoded';
            this.success = typeof success == "function" ? success : (res) => { };
            this.error = typeof error == "function" ? error : (res) => { };
            this.xhr = null;
            this.send_data = null;
            this.file = file; // 是否支持文件上传
            this.json_data = json_data;
            this.init();
        }

        init() {

            // 如果是GET+JSON格式发送则抛出异常

            if(this.json_data && this.type=='GET'){
                throw new Error("不可使用GET方式提交JSON数据");
            }else if(this.json_data && this.file ){
                throw new Error("提交文件不可使用JSON数据");

            }

            // 第一步,处理上传的数据格式
            if(!this.json_data){
                this.dataFormat();
            }
            else{
                this.dataJson();
            }

            // 第二步:如果是GET提交,则send()中不能有任何数据
            if (this.type == "GET") {
                this.getAjax();
            }else if (this.file){
                this.fileAjax();
            }
            else if (this.type == "POST") {
                this.postAjax();
            }
            // 第三步:判断后端返回信息
            this.callbackAjax();
        }

        dataFormat() {
            this.send_data = Object.entries(this.data).reduce((prev, value, index, array) => {
                if (array.length - 1 == index) {
                    return prev += `${value[0]}=${value[1]}`
                }
                else {
                    return prev += `${value[0]}=${value[1]}&`
                }

            }, "")

        }

        dataJson(){
            this.send_data = JSON.stringify(this.data);
        }

        getAjax() {
            this.url = this.url.concat('?', this.send_data,);
            this.xhr = new XMLHttpRequest();
            this.xhr.open(this.type, this.url, true);
            this.xhr.setRequestHeader("Content-Type", this.contentType);
            this.xhr.send(null);


        }

        postAjax() {
            this.xhr = new XMLHttpRequest();
            this.xhr.open(this.type, this.url, true);
            // 判断是否发送JSON数据格式
            if (this.json_data){
                this.xhr.setRequestHeader("HTTP_X_REQUESTED_WITH","XMLHttpRequest");
                this.xhr.setRequestHeader("Content-Type","application/json");
            }else{
                this.xhr.setRequestHeader("Content-Type", this.contentType);
            }
            this.xhr.send(this.send_data);

        }

        fileAjax(){
            // 注意,文件上传只能是POST形式
            this.xhr = new XMLHttpRequest();
            this.xhr.open("POST", this.url,true);
            this.xhr.send(this.data);  // 注意,这里是上传的this.data
        }


        callbackAjax() {
            this.xhr.onreadystatechange = () => {
                if (this.xhr.readyState == 4 && this.xhr.status == 200) {
                    if (this.dataType == "JSON") {
                        this.success(JSON.parse(this.xhr.responseText));
                    } else {
                        this.success(this.xhr.responseText);
                    }

                } else if (this.xhr.status == 404) {
                    this.error("请求失败,检查IP与PORT");
                } else if (this.xhr.status == 500) {
                    this.error("请求失败,服务器内部错误");
                }
            }

        }


    }
    window.Ajax = Ajax;

}())
原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13674334.html