第二章 原生 Ajax 使用

1 基本使用步骤

// 第一步 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();

// 第二步 监听接响应成功的事件
xhr.onload = () => {
    console.log('成功接收到后端的响应!', xhr.responseText);
};


// 第三步 请求初始化
// open() 方法参数:第一个参数 请求方式;第二个参数 请求URL;第三个参数 是否异步,默认值true,表示异步方式
xhr.open('GET', '/getData');

// 第四步 发送请求, 
// send() 方法 参数可以设置请求体,没有请求可以不设置参数
xhr.send();

2 发送请求

2.1 通过 URL 携带数据

可以将要发送到后端的数据以查询字符串的形式拼接到 URL中, GET、POST 等所有的请求方式都可以通过 URL 携带数据。

// 定义查询字符串
const qs = `username=${nameInp.value}&userpwd=${pwdInp.value}`;
// 请求初始化 将携带的数据以查询字符串的形式拼接到 URL 中
xhr.open('GET', '/addData?'+qs)
// 发送请求
xhr.send();

2.2 通过请求体携带数据 — 字符串

如果要向后端发送的数据较多,放在请求体中是更好的方式,需要注意的是,POST、PUT、PATCH、DELETE、OPTION、CONNECT 这些请求方式可以设置请求体,而 GET、HEAD 这两种请求方式无法请求体。

// 定义查询字符串
const qs = `username=${nameInp.value}&userpwd=${pwdInp.value}`;

// 初始化
xhr.open('POST', '/addData');

// 设置请求头  请求头一定要在 open() 之后,send() 之前设置
// 通过请求头 Content-type,告知后端请求体的类型
// xhr.setRequestHeader('Content-type', 'text/plain');
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// xhr.setRequestHeader('Content-type', 'application/json');

// 发送请求,请求体必须是字符串
xhr.send(qs)

请求体要以字符串的形式进行设置(send()方法的参数),字符串可以是以下三种格式类型:

text/plain

1. 默认的请求体类型,请求头字段 Content-type 的默认就是 text/plain
2. 请求体只要是字符串就可以,后端不会做任何处理

application/x-www-form-urlencoded

1. 需要设置请求头字段 Content-type 为 application/x-www-form-urlencoded 告知后端请求体类型
2. 请求体内容是查询字符串,如 a=100&b=200
3. 点击提交按钮提交表单(非Ajax),如果 Method 是 POST,默认请求体内容类型就是 x-www-form-urlencoded

application/json

1. 需要设置请求头字段 Content-type 为 application/json 告知后端请求体类型
2. 请求体内容是 json 格式的字符串

2.3 通过请求体携带数据 — FormData

请求体(send()的方法的参数)除了是字符串,也可以是 formData 对象,如果请求体是 FormData 对象,浏览器会自动设置请求头字段 Content-typemultipart/form-data如果需要通过 AJax 的方式上传文件,则必须使用 FormData 方式

// 方式一 创建 空的 FormData,再添加数据,可以添加文件数据或者字符串数据
var fd = new FormData();
fd.append('message', msgInput.value);
fd.append('content', 'hello ajax');
fd.append('avator', avatorInput.files[0]);  // 将文件对象添加到 FormData 中

// 方拾二 根据表单元素创建 FormData 会包含表单中所有的信息
var fd = new FormData(formElement);

FormData 对象有如下方法:

append()
set()
delete()
get()
getAll()

3 处理响应

3.1 读取响应报文

// 响应行
xhr.status;            // 响应状态码
xhr.statusText;        // 响应状态描述

// 响应头
xhr.getResponseHeader('响应头字段');        // 获取指定字段的响应头的信息
xhr.getAllResponseHeaders();           // 获取所有的响应头信息

// 响应体
xhr.responseText;        // 获取响应体体符串
xhr.response;            // 获取响应体字符串,如果响应体是特殊格式的字符串,会进行处理

3.2 处理 json 格式的响应体

如果响应体是 json 格式的字符串,一般后端会在响应头中设置 Content-typeapplication/json 告知前端响应体内容的类型。

① 方式一 使用 JSON.parse
// 监听响应结束的回调函数、
xhr.onload = function() {
    // 将响应体中 json 格式的字符串处理成对象
    var resData = JSON.parse(xhr.responseText);
}
② 方式二 设置 xhr.responseType 属性 ,通过 xhr.response获取
xhr.responseType = 'json';
xhr.onload = function() {
    xhr.response;        // 直接得到处理好的对象
}

4 响应超时

方案一 使用 timeout 事件

这里用到的 timeout 属性和 timeout 事件,IE8 浏览器是不兼容的

 // 监听响应超时的事件
xhr.ontimeout = function(){
    alert('响应超时!');
}

// 请求初始话
xhr.open('GET', '/getInfo');

// 发送请求之前设置超时时间
xhr.timeout = 5000;

// 发送
xhr.send();

方案二 兼容性方案(了解)

// 发送请求
xhr.send();

// 发送请求之后,设置单次定时,如果时间到了还没有接收到响应,中断请求
setTimeout(function(){
    // 判断如果没有响应结束
    if (xhr.readyState !== 4) {
        xhr.abort();  // 中断请求
        alert('请求超时!');
    }
}, 5000);

5 HTTP 进度事件

5.1 进度事件

readystatechange    触发至少 4 次
loadstart            开始请求的时候触发,此时 readyState 的值是 1
load                响应结束的时候触发,此时 readyState 的值是 4
error                请求失败触发,应用层面的错误也算是请求成功(如 404错误),只有网络错误才算请求失败,指请求无法发出的错误
loadend                响应结束之后触发,不论请求是否成功都会触发
progress            当开始接收响应内容,被触发多次,该事件的回调函数可以获取一个 progressEvent 对象

相关事件的触发顺序: loadstart、progress(可能会触发多次)、 load/error、loadend

5.2 readystatechagne 事件

当 XMLHTTPRequest 对象的属性 readState 的值发生变化,readystatechange 事件就会触发。readyState 的值是一个数字,不能的数字表示请求响应过程中所处的不同阶段。readyState 的值如下:

0 -- UNSET -- XHR对象已创建或已被 abort() 方法重置。 
1 -- OPENDED -- open() 方法已经被调用。
2 -- HEADERS_RECEIVED -- send() 方法已经被调用,并且响应头和响应状态已经可获得。 
3 -- LOADING -- 下载中, responseText 属性已经包含部分数据。 
4 -- DONE -- 所有响应数据接收完毕。

5.3 ProgressEvent 对象

progress 事件的回调函数可以获取一个 progressEvent 对象,该对象有如下属性:

loaded        表示当前已经下载的字节数
total        表示响应内容的总字节数

6 同步请求和异步请求

两者区别:

1. 异步请求,请求发送之后,其他同步操作继续执行; 当获取响应之后触发回调函数,回调函数进入回调队列等待主线程空闲执行
2. 同步请求,请求发送之后,其他的同步操作必须等到,响应结束之后才能继续执行

如何发送同步请求:

open() 方法的第三个参数是布尔值,true 表示异步请求,false 表示同步请求,默认值是 true。

注意: 不建议使用同步请求,目前大部分浏览器同步请求,相关事件都不会被触发。

附录 XMLHttpRequest 对象

① XHR 对象概述

1)XMLHttpRequest 对象简称 XHR 对象。

2)XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。

3)XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。

4)尽管名为 XMLHttpRequest,它并不限于和 XML 文档一起使用,它可以接收任何形式的文本文档。

② 创建 XHR 对象

使用构造函数 XMLHttpRequest 就可以创建一个 XHR 对象。

let xhr = new XMLHttpRequest();

注意:在古老的 IE 浏览器中(如:IE6),需要使用其他方式来创建 XHR 对象。

// IE5、IE6
let xhr = new ActiveXObject("Microsoft.XMLHTTP");

③ XHR对象的属性

属性名 含义
readyState 返回一个数字,表示请求的状态:
0 -- UNSET -- XHR对象已创建或已被 abort() 方法重置。
1 -- OPENDED -- open() 方法已经被调用。
2 -- HEADERS_RECEIVED -- send() 方法已经被调用,并且响应头和响应状态已经可获得。
3 -- LOADING -- 下载中, responseText 属性已经包含部分数据。
4 -- DONE -- 所有响应数据接收完毕。
status 响应状态码,如 404、200 等。
statusText 响应状态码的文本描述,如 200 对应的是 “OK”。
responseXML 接收格式为 XML 的响应数据,返回一个 document 对象。
responseText 获取响应文本,返回一个字符串。
responseType 用于设置响应内容的类型 xhr2
response 返回的类型取决于 responseType 的设置。 xhr2
timeout 设置超时时间。xhr2

④ XHR 对象的方法

方法名 含义
open() 初始化 HTTP 请求,用来指定请求方式和 URL。
xhr.open(method, url, [async], [user], [password])
send() 发送 HTTP 请求,参数可以设置请求体,没有请求体无需设置参数。
setRequestHeader() 设置 HTTP 请求头的值。必须在 open() 之后、send() 之前调用。
abort() 如果请求已被发出,则立刻中止请求。
getAllResponseHeaders() 以字符串形式返回所有的响应头。
getResponseHeader() 返回指定的响应头。

⑤ XHR 对象的事件

事件名 含义
readystatechange readyState 属性值发生变化触发该事件。
abort 请求终止时触发。
error 请求遇到错误时触发。
loadstart 接收到响应数据时触发。 xhr2
load 请求成功完成时触发。xhr2
loaded 当请求结束时触发, 无论请求成功 ( load) 还是失败 (aborerror)。xhr2
progress 当请求接收到更多数据时,周期性地触发。xhr2
timeout 在预设时间内没有接收到响应时触发。xhr2

results matching ""

    No results matching ""