AJAX
介绍
AJAX是一种网页开发技术,它的全称是“异步JavaScript和XML”。简单来说,AJAX允许网页在不重新加载整个页面的情况下,与服务器交换数据和更新部分网页内容。
我们可以用“餐馆点餐”来比喻AJAX技术:想象一下,你正在餐馆吃饭,此时你想再加一份菜,但你不想离开座位重新点餐,这时候服务员(就像AJAX技术)可以帮你把你的菜单传给厨房(服务器),然后厨房做好菜后,服务员再把菜端给你,而不需要你离开座位重新排队点餐。这样,你的用餐体验变得更加顺畅,而不需要中断。
AJAX实例
以下我们创建了一个ajax实例供参考:
<!DOCTYPE html>
<html>
<head>
<title>
你好,AJAX!
</title>
</head>
<body>
<h1 id="myh1">点击以下按钮修改内容</h1>
<button onclick="run()">RUN</button>
</body>
<script>
function run(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange= ()=>{
if(xhr.readyState==4 && xhr.status==200){
console.log('请求已完成且响应已就绪');
var myh1 = document.getElementById("myh1");
myh1.textContent = xhr.responseText;
}
}
xhr.addEventListener('readystatechange',()=>{
console.log('readyState属性改变了');
});
xhr.open('GET','<url>',true); //url是指你请求资源的目标地址
xhr.send();
}
</script>
</html>
AJAX技术是用XHR对象或Fetch API进行网络请求后获取到数据再通过操作DOM进行页面更新来实现的。
创建一个XHR对象
介绍
AJAX技术包含“网络请求”和“页面更新”两部分,其中使用XHR(即XMLHttpRequest)对象进行网络请求则是“网络请求”部分的核心。
XHR对象,全称是XMLHttpRequest对象,是JavaScript的一个内置对象,它允许网页通过JavaScript向服务器发送请求和从服务器接收数据,而不需要重新加载整个页面。这使得网页可以实现异步数据交换,是AJAX技术的核心。
语法
IE7以上(包括IE7、Firefox、Chrome、Safari 以及 Opera)的新版本浏览器创建XHR对象是使用XMLHttpRequest构造函数进行创建:
var xhr = new XMLHttpRequest();
IE7以下的老版本浏览器则是使用ActiveXObeject构造函数创建ActiveX对象,其中传入的参数为"Microsoft.XMLHTTP":
var ax = new ActiveXObeject("Microsoft.XMLHTTP");
“Microsoft.XMLHTTP”:这是传递给ActiveXObeject构造函数的参数,它指定了要创建的ActiveX控件的ProgID(程序标识符)。ProgID是用于标识COM对象(在Windows操作系统中使用的组件对象模型)的一个字符串。
使用XHR网络请求
XHR请求
在我们创建好了一个XHR对象之后,就需要使用这个对象来进行网络请求的实现了。在XHR对象中,我们使用open()方法和send()方法来实现对网络资源或本地资源进行获取,以下是这两个方法的具体信息和使用。
open()
XHR.open()方法是用来初始化一个新的请求,或重新初始化一个请求。
xhr.open("method","url","async");
参数 | 类型 | 描述 |
method | String | 填写请求的方法,如GET(获取)、POST(提交)、PUT(增加)、DELETE(删除)。 |
url | String | 填写请求资源的目标地址 |
async | Boolean | 是否为异步执行操作?true为是,false为否 |
“异步执行操作”就是当请求发送之后,当请求目标还未响应请求的时候,继续往下执行后面的代码;相反,“同步”就是指等待请求目标响应请求之后再往下执行后面的代码。但在XHR网络请求中,更加推荐使用“异步”,因为“同步”会导致JavaScript主线程被阻塞,导致其他代码不会执行。
send()
XHR.send()方法用于发送 HTTP 请求。
xhr.send("post_content");
参数 | 类型 | 描述 |
post_content | String | 用于POST发送内容,若是GET则不填。 |
如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回。
XHR响应
在XHR对象中一般通过读取responseText和responseXML属性来获取请求目标返回来的响应数据,除此之外还有一些不常用的属性:
属性 | 描述 |
responseText | 获得字符串形式的响应数据。 |
responseXML | 获得XML/HTML形式的响应数据。 |
responseType | 获得响应数据中包含的数据类型。 |
response | 返回响应的正文。返回的类型为 ArrayBuffer、Blob、Document、JavaScript Object 或字符串中的一个。 |
responseURL | 获得响应的序列化URL |
responseText获取响应数据:
document.getElementById("myDiv").innerText = xhr.responseText;
responseXML获取响应数据:
console.log(xhr.responseXML);
XHR网络请求的状态
XHR.readyState
介绍
当请求被发送给服务器时,该XHR对象会处在各个不同的阶段,而XHR对象中的readyState属性便是用来描述XHR对象所处阶段的。
它包含以下四个状态值以及对应的状态信息:
值 | 状态 | 状态描述 |
0 | UNSENT | 已创建XHR对象,但并未调用open()方法。 |
1 | OPEN | open()方法已被调用。在这个状态中,可以通过 setRequestHeader() 方法来设置请求的头部。 |
2 | HEADERS_RECEIVED | send()方法已被调用,并且头部和状态已经可获得。 |
3 | LOADING | 请求处理中,并且responseText属性已包含部分数据。 |
4 | DONE | 请求已完成且响应已就绪。 |
一般在使用XHR.readyState时会搭配着XHR.status(HTTP状态码)一起使用,如下示例:
var xhr = new XMLHttpRequest(); //创建并初始化xhr对象
if (xhr.readyState==4 && xhr.status==200){
//在“请求操作完成”且“请求成功”的状态下执行的逻辑代码
}
常见的HTTP状态码
状态码 | 状态描述 |
200 | 请求成功。 |
301 | 资源(网页等)被永久转移到其它URL。 |
404 | 请求的资源(网页等)不存在。 |
500 | 服务器内部错误,无法完成请求。 |
XHR.readyState与HTTP状态码的区别
XHR.readyState指的的是XMLHttpRequest对象的当前状态。它是一个只读属性,用xhr.readyState来读取。
HTTP状态码指的是在使用HTTP协议请求服务器完成后,由服务器发送,并作为响应的一部分的一种代码,它表明了当前请求的结果。它同样也是一个只读属性,用xhr.status来读取。
Tip:XMLHttpRequest网络请求同样也是基于HTTP协议的网络请求。
XHR.onreadystatechange
介绍
只要各种对象(如WebSocket,XMLHttpRequest)的readyState属性发生变化时,就会调用相应的处理函数。XHR.onreadystatechange方法就是会在XHR.readyState属性发生变化的时候被调用。
语法
使用XMLHttpRequest对象中的事件处理方法onreadystatechange,对其赋值一个函数来执行发生该事件之后的逻辑代码:
xhr.onreadystatechange = function(){
//当readyState属性改变时的逻辑代码
}
注册一个事件监听器来监听readystatechange事件,再执行事件发生后的回调函数:
xhr.addEventListener('readystatechange',()=>{
//当readyState属性改变时的逻辑代码
});
使用Fetch API网络请求
介绍
Fetch API 是一个现代的网络请求工具,它提供了一种更简单、更强大的方式来发起网络请求。可以直接使用JavaScript异步地请求资源,而非使用传统的XHR对象来进行网络请求。以下是一些Fetch API的基本特点:
-
基于Promise:
fetch
返回一个Promise对象,这意味着可以使用.then()
方法来处理响应,也可以使用async/await
语法。 -
灵活的参数:
fetch
接受一个URL作为必须的参数,并且可以接受一个可选的配置对象,用于自定义请求的各个方面,如方法、头信息、身体数据等。 -
模块化:
fetch
的Response和Request对象是模块化的,可以单独使用,便于更细粒度的控制。 -
跨域请求:默认情况下,
fetch
遵循同源策略,但可以通过CORS(跨源资源共享)来支持跨域请求。 -
不需要额外的库:
fetch
是原生支持的,不需要引入像jQuery这样的库。
语法
发起请求
fetch(url,options).then((response)=>{
//处理响应
}).catch((error)=>{
//处理错误
});
配置选项
const options = {
method: 'GET', // 或 'POST', 'PUT', 'DELETE', 等
headers: {
'Content-Type': 'application/json'
// 其他头部信息
},
body: JSON.stringify(data) // 如果是POST或PUT请求,可以包含一个请求体
};
处理响应
response.ok
:布尔值,表示请求是否成功。response.status
:HTTP状态码。response.statusText
:状态文本。response.headers
:响应头信息。response.json()
:将响应体解析为JSON。response.text()
:将响应体解析为文本。
示例
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json();
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('There has been a problem with your fetch operation: ', error);
});
Tip:
fetch
不会自动将HTTP错误状态(如404或500)视为拒绝,即使响应的ok
属性为false
,它也会解析为一个成功的Promise。因此,需要手动检查response.ok
或response.status
来决定是否抛出错误。
XHR和Fetch API的区别
语法:XHR使用传统的回调函数,而Fetch API基于Promise,语法更现代、简洁。
错误处理:XHR需要检查状态码和监听错误事件,Fetch API通过Promise的拒绝来处理网络错误。
默认行为:XHR默认发送cookie,Fetch API默认不发送。
进度事件:XHR提供进度事件,Fetch API需要额外处理。
兼容性:XHR在所有浏览器中都支持,Fetch API在较新浏览器中支持较好。
使用场景:XHR适用于需要兼容旧浏览器的项目,Fetch API适用于现代Web应用。
可能出现的问题
跨源资源共享(CORS)政策问题
运行代码的时候,可能会在浏览器控制台中出现以下错误提示:
<your-filename>:1 Access to XMLHttpRequest at '<your-url>' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
问题分析
该错误是由于浏览器跨源资源共享政策导致的,当你从源(本地文件或者不同域的网页)尝试通过XMLHttpRequest方法请求另一源的资源时,由于没有正确设置响应头:Access-Control-Allow-Origin 从而使得浏览器会阻止这个请求。
解决方案
如果使用的是Node.js和Express的服务器应用,可以在代码中添加如下代码:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});