原生JS的HTTP请求相关知识

本文详细介绍了HTTP响应的组成部分,包括状态码、响应头和响应主体。通过XMLHttpRequest对象,展示了如何检查HTTP状态码以判断请求是否成功,并演示了GET、POST、PUT、DELETE请求的实现。同时,讲解了处理响应数据的方法,如使用responseText和responseXML属性,以及JSON.parse转换数据。此外,还提到了URL参数的处理、MIME类型和浏览器编码的相关知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接收响应

一个完整的HTTP响应由状态码、响应头集合和响应主体组成。在收到响应后,这些都可以通过XHR对象的属性和方法使用,主要有以下4个属性

responseText: 作为响应主体被返回的文本(文本形式)
responseXML: 如果响应的内容类型是'text/xml'或'application/xml',这个属性中将保存着响应数据的XML DOM文档(document形式)
status: HTTP状态码(数字形式)
statusText: HTTP状态说明(文本形式)

在接收到响应后,第一步是检查status属性,以确定响应已经成功返回。一般来说,可以将HTTP状态码为200作为成功的标志。此时,responseText属性的内容已经就绪,而且在内容类型正确的情况下,responseXML也可以访问了。此外,状态码为304表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。

无论内容类型是什么,响应主体的内容都会保存到responseText属性中,而对于非XML数据而言,responseXML属性的值将为null

if((xhr.status >=200 && xhr.status < 300) || xhr.status == 304){
    alert(xhr.responseText);
}else{
    alert('request was unsuccessful:' + xhr.status);
}

GET

let xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', 'url', true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        console.log(JSON.parse(xmlhttp.response));
        let response = JSON.parse(xmlhttp.response);
        if (response.status == 200) {
            alert("创建成功");
        } else {
            alert("创建失败");
        }
    } else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
        alert("网络错误,请稍后重试");
    }
}

POST

let data = {
    guestRoomID : form.room_id.value,
    position : form.room_position.value,
    type : form.room_type.value,
    power: 1
}
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', 'url', true);
xmlhttp.setRequestHeader("Content-type", "application/json");
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        console.log(JSON.parse(xmlhttp.response));
        let response = JSON.parse(xmlhttp.response);
        if (response.status == 200) {
            alert("创建成功");
        } else {
            alert("创建失败");
        }
    } else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
        alert("网络错误,请稍后重试");
    }
}

//无data
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', url, true);
xmlhttp.setRequestHeader('Content-type', 'application/json');
xmlhttp.send();

//无data
let xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', url, true);
xmlhttp.setRequestHeader('Content-type', 'application/json');
xmlhttp.send(JSON.stringify());

PUT

let  xmlhttp = new XMLHttpRequest();
xmlhttp.open('PUT', 'url', true);
xmlhttp.setRequestHeader('Content-type','application/json');
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        console.log(JSON.parse(xmlhttp.response));
        let response = JSON.parse(xmlhttp.response);
        if (response.status == 200) {
            alert("创建成功");
        } else {
            alert("创建失败");
        }
    } else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
        alert("网络错误,请稍后重试");
    }
}

DELETE

let xmlhttp = new XMLHttpRequest();
xmlhttp.open("DELETE", url, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        console.log(JSON.parse(xmlhttp.response));
        let response = JSON.parse(xmlhttp.response);
        if (response.status == 200) {
            alert("创建成功");
        } else {
            alert("创建失败");
        }
    } else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
        alert("网络错误,请稍后重试");
    }
}

js的引用方法

  1. 报错Cannot use import statement outside a module的解决方法
//html
<script type="module" src="../js/index.js"></script>


//index.js
import data from './config.js'
let totalUrl = data.globalData.totalUrl;
console.log(totalUrl);

//config.js
let globalData = {
    totalUrl : 'http://wktds9.natappfree.cc'
}
export default {
    globalData
}

使用liveServer插件开始为服务器,在html右键open with live Server

JS获取浏览器之间参数

/**
*传入截取字符的属性名,返回截取的属性值
*/

function getQueryString(name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
    var r = window.location.search.substr(1).match(reg);
    if (r != null) return unescape(r[2]); return null;
}
//缺点是不支持浏览器中有中文

JS获取url参数

function parseUrl(url) {
    // 找到url中的第一个?号
    var parse = url.substring(url.indexOf("?") + 1),
        params = parse.split("&"),
        len = params.length,
        item = [],
        param = {};

    for (var i = 0; i < len; i++) {
        item = params[i].split("=");
        param[item[0]] = item[1];
    }

    return param;
}

// demo:
parseUrl("www.haorooms.com/js?name=haorooms&age=21&page=2")
// 结果
{name: "haorooms", age: "21", page: "2"}

URL参数拼接

/**
 * @description 将传入的url参数对象解析组装成字符串做为queryString中的一部分
 * @param {Object} params 参数的数组
 * @param {string} cgi 路径
 * @return {String} queryString部分字符串
 * @example : param1=value1&param2=value2&param3=value3......
 */
function convert_params(params, cgi){
    var paramsArray = [];
    for (var name in params) {
        if (paramsArray.length == 0) {
            cgi && cgi.indexOf('?') != -1 ? paramsArray.push("&") : paramsArray.push("?");
        }
        else {
            paramsArray.push("&");
        }
        paramsArray.push(name);
        paramsArray.push("=");
        paramsArray.push(params[name]);
    }
    return paramsArray.join("");
}

console.log(convert_params({"param": "value1", "param2": "value2"}, "/post/"));
// ?param=value1&param2=value2
console.log(convert_params({"param": "value1", "param2": "value2"}, "/post/?page=1"));
// &param=value1&param2=value2

获取URL后面锚点ID

http://www.haorooms.com/#haorooms

要获取后面的#haorooms。

有的同学可能还要获取浏览器地址,然后用indexOf获取到#的位置,然后在拿到#haorooms,或者其他比较繁琐的办法,今天讲一个最简单有效的方法,用js自带方法就可以获取,一句代码搞定!

var thisId = window.location.hash;

就可以直接获取到#haorooms

我们可以进行如下判断:

var thisId = window.location.hash;
if(thisId != "" && thisId != undefined){
}

浏览器编码

“只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*'(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”

无论网页的原始编码是什么,一旦被Javascript编码,就都变为unicode字符。

由HTML源码中字符集的设定决定。

<meta http-equiv="Content-Type" content="text/html;charset=xxxx">

如果上面这一行最后的charset是UTF-8或是GB2312,URL就以对应的编码。GET和POST方法的编码,用的是网页的编码。

escape()不对“+”编码。但是我们知道,网页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。

方法一:escape()

escape()来编码字符串;unescape()来解码字符串;

方法二:encodeURIComponent()

encodeURIComponent()编码,decodeURIComponent()进行解码;
encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。

该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ’ ( ) 。

其他字符(比如 :;/?😡&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

var test1="http://www.haorooms.com/My first/";
var nn=encodeURI(test1);
var now=decodeURI(test1);

http://www.haorooms.com/My%20first/
http://www.haorooms.com/My first/
 
var test1="http://www.haorooms.com/My first/";
var bb=encodeURIComponent(test1);
var nnow=decodeURIComponent(bb);

http%3A%2F%2Fwww.haorooms.com%2FMy%20first%2F
http://www.haorooms.com/My first/

GET请求

get请求的查询字符串都必须使用encodeURIComponent()编码

function addURLParam(url, name, value) {
    url += (url.indexOf("?") == -1 ? "?" : "&");
    url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
    return url;
}

HTTP请求的时限

有时,ajax操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。

新版本的XMLHttpRequest对象,增加了timeout属性,可以设置HTTP请求的时限。

xhr.timeout = 3000;

上面的语句,将最长等待时间设为3000毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个timeout事件,用来指定回调函数。

xhr.ontimeout = function(event){
    alert('请求超时!');
}

不过在超时后访问status属性则会发生错误,可以把检查status的语句放到try/catch中。

目前,Opera、Firefox和IE 10支持该属性,IE 8和IE 9的这个属性属于XDomainRequest对象,而Chrome和Safari还不支持。

xhr.open('post','test.php',true);
xhr.ontimeout = function(){
    console.log('The request timed out.');
}
xhr.timeout = 1000;
xhr.send();

FormData对象

ajax操作往往用来传递表单数据。为了方便表单处理,HTML 5新增了一个FormData对象,可以模拟表单。

首先,新建一个FormData对象。

var formData = new FormData();

然后,为它添加表单项。

formData.append('username', '张三');
formData.append('id', 123456);

最后,直接传送这个FormData对象。这与提交网页表单的效果,完全一样。

xhr.send(formData);

FormData对象也可以用来获取网页表单的值。

var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // 添加一个表单项
xhr.open('POST', form.action);
xhr.send(formData);

上传文件

新版XMLHttpRequest对象,不仅可以发送文本信息,还可以上传文件。

假定files是一个"选择文件"的表单元素(input[type=“file”]),我们将它装入FormData对象。

var formData = new FormData();

  for (var i = 0; i < files.length;i++) {

    formData.append('files[]', files[i]);

  }

然后,发送这个FormData对象。

xhr.send(formData);

进度事件的种类

进度事件用来描述资源加载的进度,主要由 AJAX 请求、<img><audio><video><style><link>等外部资源的加载触发,继承了ProgressEvent接口。它主要包含以下几种事件。

  • abort:外部资源中止加载时(比如用户取消)触发。如果发生错误导致中止,不会触发该事件。
  • error:由于错误导致外部资源无法加载时触发。
  • load:外部资源加载成功时触发。
  • loadstart:外部资源开始加载时触发。
  • loadend:外部资源停止加载时触发,发生顺序排在error、abort、load等事件的后面。
  • progress:外部资源加载过程中不断触发。
  • timeout:加载超时时触发。

MIME类型

媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 / 多功能网际邮件扩充协议)是一种标准,用来表示文档、文件或字节流的性质和格式。

网络中媒体一种格式, 在http协议中, 不认识后缀名, 只认识MIME类型, 只要你设置对MIME类型,浏览器会用指定的引擎解析对应的数据。在HTTP中,MIME类型被定义在Http响应的响应头 的Content-Type字段中。(network->head)

MIME意为多目Internet邮件扩展,它设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。
访问一个网页,获得一个资源后,浏览器通过媒体资源类型MIME Type,媒体资源类型通过http协议,由web服务器告知浏览器,更详细的说,是通过Content-Type来定义的。
例如:Content-Type: text/HTML
通常只有一些在互联网上获得广泛应用的格式才会获得一个 MIME Type,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头。

怎么获得MimeType ?
servletContext.getMimeType(file.getName());
这个方法会根据文件名自动分割出文件的后缀名,并且根据后缀名去tomcat/conf/web.xml中查取的对应关系,并返回。

服务器传到客户端的文件mime类型的详细过程:

Web服务器和浏览器(包括操作系统)中,缺省都设置了标准的和常见的MIME类型,只有对于不常见的 MIME类型,才需要同时设置服务器和客户浏览 器,以进行识别。

由于MIME类型与文档的后缀相关,因此服务器使用文档的后缀来区分不同文件的MIME类型,服务器中必须定义文档后缀 和MIME类型之间的对应关系。而客户程序从服务器上接收数据的时候,它只是从服务器接受数据流,并不了解文档的名字,因此服务器必须使用附加信息来告诉 客户程序数据的MIME类型。服务器在发送真正的数据之前,就要先发送标志数据的MIME类型的信息,这个信息使用Content-type关键字进行定义,例如对于HTML文档,服务器将首先发送以下两行MIME标识信息,这个标识并不是真正的数据文件的一部分。

Content-type: text/html
空行 “ ”

注意,第二行为一个空行,这是必须的,使用这个空行的目的是将MIME信息与真正的数据内容分隔开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值