js中的原生网络请求解读

早在很多年前,我们发送网络请求都是通过刷新或者跳转页面来获取新的网络数据,从而达到渲染不同页面的需求,用户体验是很差的,直到 ajax 横空出生,才解决了这个问题,不需要刷新页面便可以获取请求数据,这也是后来前后端分离的重要根源,大大的提高了网页性能,优化了用户体验。

而 ajax 的核心就是我们今天要学的的原生请求,**XMLHttpRequest**对象。

一. XMLHttpRequer 对象

创建: 通过 new 来创建。

1. 使用 XHR

  • open: 接收三个参数,分别为请求类型,请求的URL,请求是否异步,该方法为发送请求做好准备
  • send: 接收一个参数,请求体发送的内容,如果不发送,必须写入null,该方法开始发送请求
  • status: 相应的 HTTP 状态码,当位于 200~300 或者 等于 304 时,说明响应成功返回。
  • responseText: 作为响应体返回的文本
  • statuesText: 响应 HTTP 的状态描述
  • abort: 该方法用来取消异步请求,会停止触发事件,调用该方法后应该取消对XHR对象的引用,不要重用XHR对象。
  • onreadystatechange: 用来监听请求位于哪个阶段,该方法应该在open前调用,该事件不会接收到event对象
  • readyState: 表示当前请求位于哪个阶段

0: 未初始化,尚未调用 open

1:已经调用open,尚未调用 send

2:已经送,已经调用send,未收到响应

3:接收中,已经收到部分响应

4:完成,接收到所有响应

let xhr = new XMLHttpRequest(); // 创建XMLHttpRequest 实例
xhr.open("get", "http://127.0.0.1:3000/index", false); //设置为同步get请求
xhr.send(null); // 开始发送请求,并且阻塞后续代码执行,直到拿到响应
if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){
    console.log(xhr.responseText) // 检验状态码
}else{
    console.log('请求失败')
}

使用readyState:

每次该值的改变,都会触发readystatechange 事件,因此我们可以在不同阶段执行不同操作

let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){ // 监听请求完成
    if((xhr.status >=200 && xhr.status <300) || xhr.status == 304){
        console.log(xhr.responseText)
    }else{
        console.log('请求失败')
        }
      }
}
xhr.open("get", "http://127.0.0.1:3000/index", true); // 异步请求
xhr.send(null);

2. HTTP 头部

① 默认头部信息

每个HTTP 请求和响应都会携带头部信息,我们来看一下默认的一些请求头部

  • Accept: 浏览器可以处理的内容类型
  • Accept-Charset:浏览器可以显示的字符集
  • Accept-Encoding: 浏览器可以压缩的编码类型
  • Connection: 浏览器与服务的连接类型
  • Cookie:页面中设置的Cookie
  • Host: 发送请求页面所在的域
  • Referrer:发送请求的页面URL
  • User-Agent: 浏览器的用户代理字符串

②设置自定义头部信息

  • setRequestHeader(): 该方法接收两个参数,头部字段的名称和值,该方法必须在open之后,send 之前调用
  • getResponseHeader(): 从XHR对象获取响应头部,只需要传入获取头部的名称即可
  • getAllResponeHeaders(): 获取所有响应头信息

3. GET 请求

用于向服务器查询某些信息,数据直接显示在url中

① 传参

需要将信息编码后,添加到URL末尾,用 ? 隔开,各个参数用&隔开,参数的键值用=隔开

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

4. POST 请求

用于向服务器发送应该保存的数据,该数据在请求体中传输,只需要将要发送的数据写入send方法中即可。

let btn = document.getElementById('btn')
btn.onclick = function(){
    const xhr = new XMLHttpRequest();
    xhr.open('post', '/post', false);
    xhr.send('sssss')
}

5. XMLHttpRequest 标准2

① FormData 类型

用于将表单数据序列化,可以使用post请求模拟表单提交,使用该方法默认将请求类型,设置为表单格式。

xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded")

实例反法:

append: 接收两个参数,通过键值对的方式,将数据填入表单

let form = new FormData();
form.append('age','12')
form.append('name', '石头山')

也可以在构造函数中传入一个表单。

let form = new FormData(document.forms[0);

② 超时

用于表示发送请求后需要等待多少毫秒,如果响应不成功就中断请求

timeout: 用来设置超时时间,如果超时则会触发 ontimeout 事件,同时 readyState 的状态也会变成 4,同时调用 onreadystatechange 事件,并且超时之后访问 statues 属性会出错
切记,同步请求不能设置超时

xhr.open('post', '/post', true); // 此处只能为 true 
xhr.timeout = 1000;
xhr.ontimeout = function(){
    console.log('请求超时')
    }
xhr.send(null)

二. 进度事件

  • loadstart: 在接收到响应的第一个字节时触发
  • progress: 在接收响应期间反复触发
  • error:在请求出错时触发
  • abort:在调用 abort()终止连接时触发
  • load: 在成功接收完响应时触发
  • loadend:在通信完成时,在error,abort,load之后触发

1. load事件

该属性用来题代 readystatechange 事件,但是有一个问题,只有从服务器收到响应,无论状态码是什么,都会触发该事件,因此还需要检验状态码来确保数据有效。

            const xhr = new XMLHttpRequest();
            xhr.open('get', '/index', true);
            xhr.onload = function(){
                if((xhr.status >= 200 && xhr.status<300) || xhr.status === 304){
                    console.log(xhr.responseText,'ss11');
                }else{
                    console.log('请求错误')
                }
            }
            xhr.send(null)

2. progress 事件

在数据接收期间,该事件反复触发,该事件对象有三个属性

  • lengthComputable: 表示进度信息是否可用
  • position:接收到的字节数
  • totalSize: 是响应体头部 Content-Length 的总字节数
            xhr.onprogress = function(event) {
                if(event.lengthComputable){
                    console.log(event.total, event.position)
                }
            }

三. 跨资源共享

1. 跨域安全策略

默认情况XHR只能访问与发起请求的页面在同一个域内的资源。

  • 原生跨域:给open传入一个绝对路径则跨源访问
  • 限制:

1.不能是使用setRequestHeader() 设置自定义头部

2.不能发送和接收cookie

3.getAllResponseHeaders() 方法始终返回 空字符串

因此,在访问本地资源时使用相对路径,访问远程资源时使用绝对路径

2. 预检请求

通过该机制,允许使用自定义头部,除GET和POST外的方法,在发送请求时先发送一个预检请求,这个请求使用OPTIONS方法发送以下头部。

  • Origin:与简单请求相同
  • Access-Control-Request-Method: 请求希望使用的方法
  • Access-Control-Request-Headers: 自定义头部列表

服务器可以确定是否允许这种类型的请求。会在响应中发送如下头部

  • Access-Control-Allow-Origin: 允许的同源
  • Access-Control-Allow-Methods: 允许的方法
  • Access-Control-Allow-Headers: 允许的自定义头部
  • Access-Control-Allow-Max-Age: 缓存预检请求的秒数

预检请求返回后,会缓存一段时间,在这段时间内再次访问不需要预检。

3. 凭据请求

默认情况下,跨源请求不提供凭据,cookie,http认证,SSl证书。可以通过将withCredentials 属性设置为true来表明请求会发送凭证。

如果服务器允许携带,则在响应头部添加

Access-Control-Allow-Credentials: true.

四. 替代性跨源技术

1. 图片探测

2. JSONP

总结

作者:石头山_S原文地址:https://blog.csdn.net/SK_study/article/details/123768485

%s 个评论

要回复文章请先登录注册