原生js实现http请求--模拟jquery的ajax函数

js原生方式发送http请求

1.基本原理

使用原生JavaScript调用API可以通过XMLHttpRequest对象来发送HTTP请求。下面是一个示例代码:

var xhr = new XMLHttpRequest(); // 创建XMLHttpRequest对象
xhr.open('GET', 'https://api.example.com/data'); // 设置请求的URL和类型(这里为GET)
xhr.onreadystatechange = function() { // 定义状态改变时的处理函数
    if (xhr.readyState === 4 && xhr.status === 200) { // 当请求完成且返回正常结果时
        var responseData = JSON.parse(xhr.responseText); // 将返回的JSON字符串转换为对象或其他格式
        console.log(responseData); // 输出获取到的数据
    } else {
        console.error("Error occurred while fetching data."); // 若有错误则打印错误信息
    }
};
xhr.send(); // 发送请求

上述代码中,我们首先创建了一个XMLHttpRequest对象,然后使用open()方法指定要发送的请求的URL和类型(此处为GET请求)。在onreadystatechange事件处理程序中,我们判断请求的状态和返回的状态码,如果都符合条件,就将返回的数据进行处理并输出;否则,会显示相应的错误消息。最后,我们使用send()方法发送请求。

readyState的不同值,代表了不同的状态。当其变为4, 就可以访问从服务器返回的数据了。

readyState状态枚举:

0:尚未初始化
1:正在加载
2:加载完毕
3:正在处理
4:处理完毕

另附http请求相应代码:

200: 请求成功
202: 请求被接受但处理未完成
400: 错误请求
404: 请求资源未找到
500: 内部服务器错误

status返回200,代表请求成功了。

2.@RequestParam方式传参

如果后端接口接收参数是采用@RequestParam注解接收参数,即URL-Encoded方式传参。

Tips:

@RequestParam用来处理 Content-Typeapplication/x-www-form-urlencoded 编码的内容,Content-Type默认为该属性。

示例代码如下:

//URL-Encoded方式传参 
const xhr = new XMLHttpRequest;
xhr.onloadend = function () {
    // 接收请求后端返回的数据
    let result = xhr.responseText;
    // console.log(result);
    // 由于大部分接口返回的数据都是JSON格式,所以需要转化
    const data = JSON.parse(result)
    console.log(data); // 可查看转化后的数据
    document.getElementById("Certificate").value = data.data.certificate;
}

var url = "https://www.baidu.com/getUserInfo";//地址为伪地址,随便写的

xhr.open("post", url);//如果是get请求,改成get即可
// 设置请求头
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");//URL-Encoded params方式参数
// 参数设置在send里面,参数+值
var params = {"userName": "xiaohuihui", "pwd": "88888888"};
xhr.send("params=" + JSON.stringify(params).toString());//这里的key是params,value为一个JSON字符串

注意

上面示例采用的是XMLHttpRequestonloadend方法监听返回结果,也是可以的。XMLHttpRequest相关的监听事件有:

onabort:当request被停止时触发.

onerror:当request遭遇错误时触发。

onload:请求成功完成时触发。

onloadend:当请求结束时触发,无论请求成功(load)还是失败(abort 或 error)。

onloadstart:接受到响应数据时触发。

onprogress:当请求接收到更多数据时,周期性触发。

timeout: 在预设时间内没有接收到响应时触发

3.@RequestBody方式传参

先介绍一下@RequestBody的使用场景:

注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/jsonapplication/xml等类型的数据。

application/json类型的数据而言,使用注解@RequestBody可以将body里面所有的json数据传到后端,后端再进行解析。

示例代码如下:

const xhr = new XMLHttpRequest;
xhr.onloadend = function () {
    // 接收请求后端返回的数据
    let result = xhr.responseText;
    // console.log(result);
    // 由于大部分接口返回的数据都是JSON格式,所以需要转化
    const data = JSON.parse(result)
    console.log(data); // 可查看转化后的数据
    document.getElementById("Certificate").value = data.data.certificate;
}

var url = "https://www.baidu.com/getUserInfo";//地址为伪地址,随便写的

xhr.open("post", url);
// 设置请求头
xhr.setRequestHeader("Content-Type", "application/json");//json格式参数

// 参数设置在send里面,json格式参数
var params = {
    "userName": "xiaohuihui",
    "pwd": "88888888"
};
xhr.send(JSON.stringify(params));

URL-Encoded传参方式不一样的地方,主要是请求头中Content-Type的值。

 

2024-07-02 14:16:30【出处】:https://blog.csdn.net/weixin_36152775/article/details/135637529

=======================================================================================

原生js实现http请求--模拟jquery的ajax函数 

 有时页面用到请求,但又不想引入jquery或者其他网络请求,增加代码冗余,增加对代码简便化,那不使用ajax情况下,可以直接使用原生js进行封装函数。原生的js通过XMLHttpRequest 对象进行的的。具体可查阅W3school的XMLHttpRequest 对象。

1、封装可供请求调用的函数

function httpRequest(paramObj,fun,errFun) {
    var xmlhttp = null;
    /*创建XMLHttpRequest对象,
     *老版本的 Internet Explorer(IE5 和 IE6)使用 ActiveX 对象:new ActiveXObject("Microsoft.XMLHTTP")
     * */
    if(window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    }else if(window.ActiveXObject) {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    /*判断是否支持请求*/
    if(xmlhttp == null) {
        alert('你的浏览器不支持XMLHttp');
        return;
    }
    /*请求方式,并且转换为大写*/
    var httpType = (paramObj.type || 'GET').toUpperCase();
    /*数据类型*/
    var dataType = paramObj.dataType || 'json';
    /*请求接口*/
    var httpUrl = paramObj.httpUrl || '';
    /*是否异步请求*/
    var async = paramObj.async || true;
    /*请求参数--post请求参数格式为:foo=bar&lorem=ipsum*/
    var paramData = paramObj.data || [];
    var requestData = '';
    for(var name in paramData) {
        requestData += name + '='+ paramData[name] + '&';
    }
    requestData = requestData == '' ? '' : requestData.substring(0,requestData.length - 1);
    console.log(requestData)
    
    /*请求接收*/
    xmlhttp.onreadystatechange = function() {
    if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      /*成功回调函数*/
      fun(xmlhttp.responseText);
    }else{
        /*失败回调函数*/
        errFun();
    }
    }            
    
    /*接口连接,先判断连接类型是post还是get*/
    if(httpType == 'GET') {
        xmlhttp.open("GET",httpUrl,async);
    xmlhttp.send(null);
    }else if(httpType == 'POST'){
        xmlhttp.open("POST",httpUrl,async);
        //发送合适的请求头信息
        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
        xmlhttp.send(requestData); 
    }
}

 

 

2、调用方法

/*请求参数*/
var paramObj = {
    httpUrl : 'https://mp.csdn.net',
    type : 'get',
    data : {
        name : 'xuexi',
        sex : '学习'
    }
}
/*请求调用*/
httpRequest(paramObj,function(respondDada) {
    //这里编写成功的回调函数
    console.log(respondDada)
},function() {
    alert('网络错误')
});

3、总结

在简单的Html页面不需要引入额外的类库时,可以使用原生请求,或者是引入的库,不满足自己的需求时,可以使用原生来达到自己的需要,掌握原生是根本,其他都是变种;

 

2024-07-02 11:34:50【出处】:https://blog.csdn.net/u010774409/article/details/136671702

个人使用

根据上面封装的类库,我自己做了部分调整,主要是为了兼容现有的ajax的请求代码和参数类型

function ajaxRequest(paramObj,successFun,errorFun) {
    var xmlhttp = null;
    /*创建XMLHttpRequest对象,
     *老版本的 Internet Explorer(IE5 和 IE6)使用 ActiveX 对象:new ActiveXObject("Microsoft.XMLHTTP")
     * */
    if(window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    }else if(window.ActiveXObject) {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    /*判断是否支持请求*/
    if(xmlhttp == null) {
        alert('你的浏览器不支持XMLHttp');
        return;
    }
    /*请求方式,并且转换为大写*/
    var httpType = (paramObj.type || 'GET').toUpperCase();
    /*数据类型*/
    var dataType = paramObj.dataType || 'json';
    /*请求接口*/
    var url = paramObj.url || '';
    /*是否异步请求*/
    var async = paramObj.async || true;
    /*请求参数--post请求参数格式为:foo=bar&lorem=ipsum*/
    var paramData = paramObj.data || [];
    var requestData = '';
    for(var name in paramData) {
        requestData += name + '='+ paramData[name] + '&';
    }
    requestData = requestData == '' ? '' : requestData.substring(0,requestData.length - 1);
    
    /*请求接收,可以监听onreadystatechange,或onloadend事件*/
    xmlhttp.onloadend = function() {    
    if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      /*成功回调函数*/
      successFun != undefined ? successFun(xmlhttp.responseText) : paramObj.success(xmlhttp.responseText);
    }else{
        /*失败回调函数*/
        console.error("Error occurred while fetching data."); // 若有错误则打印错误信息
        errorFun != undefined ? errorFun(xmlhttp, xmlhttp.status, "error...") : paramObj.error(xmlhttp, xmlhttp.status, "error...");
    }
    }            
    
    /*接口连接,先判断连接类型是post还是get*/
    if(httpType == 'GET') {
        xmlhttp.open("GET",url,async);
    xmlhttp.send(null);
    }else if(httpType == 'POST'){
        xmlhttp.open("POST",url,async);
        //发送合适的请求头信息
        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
        xmlhttp.send(requestData); 
    }
}

/*请求参数配置*/
        ajaxConfig={
            type: 'get',
            url: 'http://timor.tech/api/holiday/year/?type=Y&week=N',
            dataType: 'json',
            data : {
                name : 'xuexi',
                sex : '学习'
            },
            success: function(data) {
                console.log('success', data)
            },
            error: function(xhr, textstatus, error) {
                console.log('error', textstatus, error)
            }
        }

/*请求调用*/
ajaxRequest(ajaxConfig)

 具体的使用示例,可参考万年历:万年历(hao123)代码

 

=======================================================================================

对原生HTTP请求的理解与总结

全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/10946165.html,多谢,=。=~

 

术语

HTTP:超文本传输协议,规定Web浏览器如何从Web服务器获取文档和向Web服务器提交表单内容,以及Web服务器如何响应这些请求和提交;

(HTTP不在脚本控制下,只当用户点击链接、提交表单、输入URL时发生。但是js可操纵HTTP,例如设置window对象的location属性、调用表单的submit()方法会初始化HTTP请求,页面会重新加载。)

Ajax:使用脚本操纵HTTP的Web应用架构,实现与Web服务器的数据交换,不会导致页面重载,客户端从服务器“拉”数据,可利用XMLHttpRequest对象实现;

Comet:使用脚本操纵HTTP的Web应用架构,与Ajax相反,服务器向客户端“推”数据,可利用EventSource对象实现;

XMLHttpRequest:定义了用脚本操纵HTTP的API;

(XMLHttpRequest对象支持包括XML在内的任何基于文本的格式,能用于HTTP和HTTPS请求,涉及HTTP请求或响应的所有活动)

 

XMLHttpRequest的使用

实例化(IE7及以后):

var request = new XMLHttpRequest();

模拟XMLHttpRequest构造函数(IE5、IE6):

复制代码
if (window.XMLHttpRequest === undefined) {
    window.XMLHttpRequest = function() {
        try {
            return new ActiveXObject("MSXML2.XMLHttp.6.0");
        }
        catch (e1) {
            try {
                return new ActiveXObject("MSXML2.XMLHttp.3.0");
            }
            catch (e2) {
                throw new Error("XMLHttpRequest is not supported");
            }
        }
    }
}
复制代码

HTTP请求(请求的方法或动作、请求的URL、请求头、请求体):

request.open("GET", "/log.php");    // 请求的方法、URL
request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");   // 请求头
request.send(null);   // 请求体

HTTP响应(数字+文字的状态码、响应头、响应体):

复制代码
request.onreadystatechange = function() {
    // HTTP的请求状态readyState
    // 0:open尚未调用
    // 1:open已调用
    // 2:接收到头信息
    // 3:接收到响应主体
    // 4:响应完成
    
    // HTTP状态码status
    // 2xx:代表请求已成功被服务器接收、理解、并接受
    if(request.readyState === 4 && request.status === 200) {
        // responseText属性:MIME类型的文本响应,如:text/css
        // responseXML属性:Document对象类型,如:XML、XHTML
        console.log(request.responseText);
    }
};
复制代码

 响应解码

复制代码
request.onreadystatechange = function() {
    if (request.readyState === 4 && request.status === 200) {
        var type = request.getResponseHeader("Content-type");
        if (type.indexOf("xml") !== -1 && request.responseXML) {
            console.log(request.responseXML);   // Document对象响应
        } else if (type === "application/json"){
            console.log(JSON.parse(request.responseText));   // Json响应
        } else {
            console.log(request.responseText);   // 字符串响应
        }
    }
};
复制代码

 

请求主体编码(POST请求)

1、表单编码(对名字和值进行URL编码(即使用十六进制转义码替换特殊字符)、使用=分开编码后的名字和值、使用&连接名/值对)

PS:<input type="submit">定义用于向表单处理程序(form-handler)提交表单的按钮,自带表单编码功能。

POST请求必须设置请求头:

request.open("POST",url);
request.setRequestHeader("Content-type","application/x-www-form-urlencoded"); request.send(encodeFormData(data));

 GET请求只需跟在url连接后即可:

request.open("GET", url + "?" + encodeFormData(data));
request.send(null);

表单编码函数encodeFormData:

复制代码
// 对象属性的表单编码
function encodeFormData(data) {
    if (!data) return "";   // 如果data非对象则返回空字符串
    var paris = [];   // 保存名=值对
    for(var name in data) {
        if (!data.hasOwnProperty(name)) continue;   // 跳过继承属性
        if (typeof data[name] === "function") continue;   // 跳过方法
        var value = data[name].toString();   // 将值转换为字符串
        name = encodeURIComponent(name.replace("20%", "+"));   // 编码名字
        value = encodeURIComponent(value.replace("20%", "+"));   // 编码值
        paris.push(name + "=" +value);
    }
    return paris.join("&");   // 使用"&"连接名/值对
}
复制代码

2、JSON编码(使用JSON.stringify()方法)

request.open("POST",url);
request.setRequestHeader("Content-type","application/json");
request.send(JSON.stringify(data));

3、XML编码(send方法中传递XML Document对象)

<query>
    <find zipcode="02134" radius="1km">
        pizza
    </find>
</query>
复制代码
function createXML(what, where, radius) {
    // Create an XML document with root element <query>
    var doc = document.implementation.createDocument("", "query", null);
    var query = doc.documentElement;   // <query>元素
    var find = doc.createElement("find");   // 创建<find>元素
    query.appendChild(find);   // 把<find>添加至<query>中
    find.setAttribute("zipcode", where);   // 设置<find>的属性
    find.setAttribute("radius", radius);
    find.appendChild(doc.createTextNode(what));   // 设置<find>的内容
    return doc;
}

// 会自动设置Content-type头
request.send(createXML("pizza", "02134", "1km"));
复制代码

4、文件上传

 HTML表单<input type="file">始终能上传文件;XMLHTTPRequest无法实现;XHR2可以通过向send()方法传入File对象实现(文件类型是更通用的二进制大对象Blob类型中的一个子类型)。

5、multipart/form-data请求

当HTML表单同时包含文件上传元素和其他元素时,必须使用Content-type为multipart/form-data的特殊方式提交表单,该编码使用长“边界”字符串把请求主体分离成多个部分。

XHR2定义了新的FormData API,容易实现多部分请求主体(使用FormData()构造函数创建FormData对象,然后按需多次调用这个对象的append()方法把个体的“部分”(字符串、File或Blob对象)添加到请求中)。

复制代码
function createFormData(data) {
    if (typeof FormData === "undefined") {
        throw new Error("FormData is not implemented");
    }
    var formData = new FormData();
    for(var name in data) {
        if (!data.hasOwnProperty(name)) continue;
        var value = data[name];
        if (typeof value === "function") continue;
        formData.append(name, value);
    }
    return formData;
}

request.send(createFormData({user: "aaa", text: "bbb"}));
复制代码

 

HTTP请求无法完成的3种情况

1、timeout事件:请求超时;

2、abort事件:请求中止;

3、error事件:比如太多重定向这样的网络错误会阻止请求完成;

 

2024-07-02 11:38:09【出处】:https://www.cnblogs.com/dreamsqin/p/10946165.html

=======================================================================================

posted on 2024-07-02 11:37  jack_Meng  阅读(310)  评论(0编辑  收藏  举报

导航