AJAX,全称是 Asynchronous JavaScript and XML,也就是异步的JavaScript和XML,是一种通过JavaScript在后台与服务器通信、实现网页局部更新和无刷新交互的技术思想。它是一组Web编程技术的组合,而不是某种单一的技术或者某种编程语言。
要详细了解AJAX,首先需要弄清楚以下几个问题:
什么是异步通信?它和同步通信有什么区别?
想象一下这样一个场景:你在浏览某个网页,在某个表单上提交了一些信息或者在点击了某个下拉的选项框,然后网页卡住了。你不能用滚轮拖动这个网页,也不能点击任何东西,直到你提交的东西传上去或者这个下拉框出现详细选项。出现这种情况的原因就是因为网页采取了同步通信的实现方式,而刚刚很不幸你的网络有些波动。
通过上面这个经历,我们对同步通信的流程有了一定的认知:
用户发起通信 ——> 一直等待 ——> 通信完成,获得结果 ——> 执行后面的代码可以发现,当我们的网络因为某种原因突然变慢、网络请求无法完成,我们就不能对网页做任何操作,这在用户体验的角度上讲是致命的。
而异步通信的流程是这样的:
用户发起通信 ——> 先不管通信,执行后续的代码 ——> 等到了通信结果 ——> 执行回调,处理结果它和同步通信最大的区别在于,异步通信不会阻塞用户操作。当用户发起通信后,用户依然可以浏览网页其它地方的内容,直到通信处理完成,或者等到用户突然发现家里的网欠费了。
至于为什么同步通信会因为网络原因被阻塞——因为JavaScript在浏览器中是单线程的,采用异步通信,浏览器就可以在后台发送请求,在前端继续响应用户的操作。
为什么是JavaScript?别的语言不可以吗?
AJAX是一种浏览器环境下的技术,当这种异步通信思想出现时(2005年),浏览器中唯一被所有平台原生支持、能直接操作页面、能发起网络通信的语言就是JavaScript。而别的语言想运行在浏览器环境下,要么兼容性不行,要么依赖插件,要么安全性不好,要么以上都占。所以自然而然的,JavaScript成为了实现AJAX的指定语言。
什么是XML?它和HTML有什么区别?它和现在的JSON有什么区别?
XML是Extensible Markup Language,中文名是“可扩展标记语言”,用来描述数据结构,标签由开发者进行定义,使用时需要由应用程序进行解释。
<user>
<name>张三</name>
<age>25</age>
<hobbies>
<hobby>读书</hobby>
<hobby>跑步</hobby>
</hobbies>
</user>HTML是Hyper Text Markup Language,中文名是“超文本标记语言”,用来展示网页,标签是预定义的,浏览器知道如何渲染它们。
<!DOCTYPE html>
<html>
<head><title>示例</title></head>
<body>
<h1>标题</h1>
<p>段落<br>
<img src="a.png" alt="图">
</body>
</html>JSON是JavaScript Object Notation,中文名是“JavaScript对象表示法”,常用键值对和数组来表示数据,支持数据类型区分,能够方便地转化为JavaScript对象。
{
"name": "张三",
"age": 25,
"hobbies": ["读书", "跑步"]
}在早期的AJAX中,返回的数据是XML形式的,而相同数据下JSON使用更少的字符、数据类型清晰、结构紧凑,在技术演化中逐渐取代了XML,成为AJAX中主流的返回数据类型。
我们已经了解了AJAX,它是一种用JavaScript实现的异步通信技术,在通信时采用JSON作为返回数据类型。接下来我们的问题是:
如何实现AJAX?
这是一门成熟的技术,古早的方法有XMLHttpRequest,JavaScript原生的方法有fetch API,第三方库有axios。我们以fetch API为例,讲述一下如何实现AJAX。
fetch('/api/user')
.then(res => res.json())
.then(data => {
document.getElementById('name').innerText = data.name;
});这是一个简短的AJAX示例代码,其中:
fetch('/api/user')它负责向同域名下的/api/user路径发一条GET请求,在发起请求时它会返回一个Promise,当服务器的响应体抵达后,它会将Promise兑现为Response。
fetch()的默认方法是GET,也可以通过指定method参数来发送POST请求。
.then(res => res.json())res是上一步fetch返回的Response对象,res => res.json()是箭头函数的写法,等价于
res => {
return res.json();
}也等价于
function(res) {
return res.json();
}res.json()负责将服务器的响应体解析为JSON。但是服务器的响应包不是一块到达的,先抵达的是响应头,res.json()收到响应头后也会返回一个Promise,当响应体解析完成之后,这个Promise会兑现为JSON。这个过程同样是异步的,当解析完成之后第二个.then才会执行回调。
.then(data => {
document.getElementById('name').textContent = data.name;
});data是上一步res.json()解析得到的JavaScript对象。假如JSON数据是
{
"name": "张三",
"age": 25
}那么得到的JavaScript对象就是
{
"name": "张三", "age": 25}最后
document.getElementById('name').innerText = data.name负责按id查找DOM结构,将id = name的标签中的文字替换为张三。最终可以得到:
<span id="name">张三</span>一次完整的AJAX请求流程为:
时间轴:
发起 fetch
|
| Promise 处于 pending
|
服务器开始响应
|
| 响应头到达
| Promise 变成 fulfilled,得到 Response 对象
| 此时可以访问 res.status、res.headers
|
| 响应体还在传输中...
|
| 调用 res.json(),返回一个新的 Promise
| 这个新 Promise 等待响应体读完并解析
|
响应体读完并解析完成
|
| 新 Promise 变成 fulfilled,得到 JavaScript 对象
| 此时可以访问 data.name什么是Promise和Response?
我们在上文中多次提到了这两个名词,接下来我们解释一下它们。
- Promise:
它代表一个“将来才会知道结果”的值。你可以理解为在餐厅点餐后领取到的号码牌,领到号之后你可以继续做别的事,等到叫号之后再去取餐。
Promise的初始状态是pending,表示等待状态;
Promise的成功状态是fulfilled,表示有处理结果了,交给.then()处理;
Promise的失败状态是rejected,表示出了问题,交给.catch()处理。
- Response:
它代表一次HTTP响应的完整信息,包含状态码、状态文本、响应头、响应体。
其中,当响应头抵达时,fetch的Promise从pending改成fulfilled并兑现Response。此时可以根据响应头的内容来决定是否继续处理响应体。
Response的常用属性有:
res.ok // 布尔值,状态码在 200-299 之间时为 true
res.status // 数字,如 200、404
res.statusText // 字符串,如 "OK"
res.headers // 响应头对象
res.url // 实际请求的 URL我们的示例代码还可以改进一下:
fetch('/api/user',{
headers: { // 加入请求头
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res => {
if (!res.ok) { // 检查状态码并抛出错误状态
throw new Error(`HTTP ${res.status}`);
}
return res.json();
})
.then(data => {
document.getElementById('name').innerText = data.name;
})
.catch(err => { // 异常处理机制
console.error('请求失败:', err);
});以上就是本文的全部内容,如有谬误,欢迎在评论区指正。
评论 (0)