随着前端技术的发展,Web的作用已经从最初的“展示信息”发展出了更多更丰富的功能。我们在浏览网页的时候希望更多的与页面有交互,而交互的时候如果每次交互重新渲染页面,那么用户体验就会很差。Ajax就是在这样的情况下应运而生的。Ajax(异步JavaScript和XML)是一种在Web应用程序中实现这种交互的技术。它允许用户与服务器进行异步交互,从而更新部分页面内容,而不需要刷新整个页面,这极大的提升了用户体验。
本文将对Ajax的工作原理、XMLHttpRequest对象的属性、方法和事件进行深入理解,并通过JSONPlaceHolder为数据服务的案例,进一步阐述Ajax及XMLHttpRequest对象的用法。
Ajax的工作原理
Ajax的核心思想是异步,使用Ajax相当于在用户和服务器之间加了一个中间层,使用户操作与服务器响应异步化。
Ajax通过XMLHttpRequest对象向服务器发送异步请求,发送请求到服务器响应并返回数据的过程中,用户可以继续与网页交互,而不会陷入请求等待。服务器返回数据后,再用JS函数根据数据对DOM操作更新部分页面。
所以Ajax的最主要的作用就是异步请求数据,我们可以将发送Ajax请求比作寄快递,而Ajax充当的角色则是快递员,我们只需要将需要寄的东西交给他,他会帮我们送达目的地,最终快递员将结果反馈给我们。
XMLHttpRequest对象的属性、方法和事件
XMLHttpRequest对象是ajax的核心机制,是使用Ajax实现异步交互的核心组件,所有请求的发送和响应的接收都依靠XMLHttpRequest对象所提供的属性、方法及事件。
下面将对XMLHttpRequest对象的属性、方法和事件做详细的说明。
XMLHttpRequest 常用对象方法
方法 | 描述 |
---|---|
new XMLHttpRequest() | 创建新的 XMLHttpRequest 对象 |
abort() | 取消当前请求 |
getAllResponseHeaders() | 返回头部信息 |
getResponseHeader() | 返回特定的头部信息 |
open(method, url, async, user, psw) | 规定请求 method:请求类型 GET 或 POST url:文件位置 async:true(异步)或 false(同步) user:可选的用户名称 psw:可选的密码 |
send() | 将请求发送到服务器,用于 GET 请求 |
send(string) | 将请求发送到服务器,用于 POST 请求 |
setRequestHeader(header, value) | 向请求添加 HTTP 头部 header:规定头部名称 value:规定头部值 |
open方法中method字段表示http协议中的请求方法,涉及到http协议的内容,由于本文重点讲解Ajax,如需了解更多http协议的内容,可前往HTTP|MDN自行查阅
XMLHttpRequest 常用对象属性
属性 | 描述 |
---|---|
readyState | 保存 XMLHttpRequest 的状态 0:请求未初始化 1:服务器连接已建立 2:请求已收到 3:正在处理请求 4:请求已完成且响应已就绪 |
responseText(现在一般不用) | 以字符串返回响应数据 |
responseXML(现在一般不用) | 以 XML 数据返回响应数据 |
status | 返回请求的状态号 常见状态号: 200: “OK” 403: “Forbidden” 404: “Not Found” 如需完整列表请访问 Http 消息参考手册 |
statusText | 返回状态文本(比如 “OK” 或 “Not Found” |
**注意:**现在数据交换格式一般为JSON,新的Ajax提供了对应接口,可用responseType属性设置返回值类型为json,然后接收数据使用response即可获得json数据,后文实例中将会具体给出应用的例子
XMLHttpRequest 常用对象事件
事件 | 触发条件 |
---|---|
onreadystatechange | 每当xhr.readyState改变时触发;但xhr.readyState由非 0 值变为 0 时不触发。 |
onloadstart | 调用xhr.send()方法后立即触发,若xhr.send()未被调用则不会触发此事件。 |
onprogress | xhr.upload.onprogress在上传阶段(即xhr.send()之后,xhr.readystate=2之前)触发,每 50ms 触发一次;xhr.onprogress在下载阶段(即xhr.readystate=3时)触发,每 50ms 触发一次。 |
onload | 当请求成功完成时触发,此时xhr.readystate=4 |
onloadend | 当请求结束(包括请求成功和请求失败)时触发 |
onabort | 当调用xhr.abort()后触发 |
ontimeout | xhr.timeout不等于 0 ,由请求开始即 onloadstart 开始算起,当到达xhr.timeout 所设置时间请求还未结束即 onloadend ,则触发此事件。 |
onerror | 在请求过程中,若发生 Network error 则会触发此事件(若发生 Network error 时,上传还没有结束,则会先触发 xhr.upload.onerror,再触发 xhr.onerror ;若发生 Network error 时,上传已经结束,则只会触发xhr.onerror )。注意,只有发生了网络层级别的异常才会触发此事件,对于应用层级别的异常,如响应返回的xhr.statusCode是 4xx 时,并不属于 Network error ,所以不会触发 onerror 事件,而是会触发 onload 事件。 |
JSONPlaceHolder为数据服务的案例
这一部分将阐述如何使用Ajax获取JSONPlaceHolder的数据,在此之前,我们先来一起梳理一下发送一个Ajax请求的一般步骤(IE以及其他浏览器老版本已经大部分弃用,所以下面方法中未考虑兼容性问题)
1. 创建Ajax核心对象XMLHttpRequest
var xhr = new XMLHttpRequest()
2.事件处理函数
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
succ(this.response);//响应成功函数
} else {
fail(new Error("HTTP status Rxception"));//响应失败函数
}
};//响应状态变化时触发此函数,可用其他事件代替
3.发送Ajax请求
xhr.open("GET", “https://jsonplaceholder.typicode.com/posts”);
xhr.responseType = "json";//设置返回类型为JOSN
xhr.send();
以上即一般情况发送Ajax请求的一般步骤,下面将演示如何使用Ajax和XMLHttpRequest对象从JSONPlaceholder API获取数据:
let xhr. = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(this.response);
}
};
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts/1");
xhr.responseType = "json";
request.send();
除此之外,还可以用http的其他方法完成更多应用:
使用POST方法提交表单
// 获取表单数据
var formData = new FormData(document.querySelector('form'));
// 创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 注册请求状态变化事件处理函数
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 201) {
console.log(xhr.responseText);
}
};
// 初始化请求
xhr.open('POST', 'https://jsonplaceholder.typicode.com/posts');
// 发送请求
xhr.send(formData);
使用PUT方法更新资源
var updateData = {
id: 1,
title: 'Updated Title',
body: 'Updated Body Text'
};
// 创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 注册请求状态变化事件处理函数
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
// 初始化请求
xhr.open('PUT', 'https://jsonplaceholder.typicode.com/posts/1');
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/json');
// 发送请求
xhr.send(JSON.stringify(updateData));
使用DELETE方法删除资源
JavaScript复制代码// 创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 注册请求状态变化事件处理函数
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
// 初始化请求
xhr.open('DELETE', 'https://jsonplaceholder.typicode.com/posts/1');
// 发送请求
xhr.send();
总结
其实通过 XMLHttpRequest
进行网络请求,这种方式已经有点老旧了,但是我们仍然有必要了解Ajax请求的核心过程,后续基于原生Ajax的框架虽然封装了内部细节使用更方便,但是其核心步骤还是一样的。
PS:参考文章中提到,Ajax配置和调用方式非常混乱,近几年刚刚出来的Fetch提供了一个更好的替代方法,它不仅提供了一种简单,合乎逻辑的方式来跨网络异步获取资源,而且可以很容易地被其他技术使用。
参考文章:
- https://juejin.cn/post/6844904114896240647
- https://segmentfault.com/a/1190000019891237
- https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started
- https://jsonplaceholder.typicode.com/