AJAX,即 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而 不用刷新整个网页。
后来,AJAX 这个词就成为 JavaScript 脚本发起 HTTP 通信的代名词,也就是说,只要用脚本发起通信,就可以叫做 AJAX 通信。
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
具体来说,AJAX 包括以下几个步骤:
概况来说,AJAX 通过原生的 XMLHttpRequest 对象发出 HTTP 请求,得到服务器返回的数据后,再进行处理 。
XML 可扩展标记语言,是一种用于标记电子文件使其具有结构性的标记语言。XML 被用于存储和传输数据。
XML 和 HTML 类似,不同的是 HTML 中都是预定义标签,而 XML 中没有预定义标签,全都是自定义标签,用来表示一些数据。
例如,对于一个学生数据 name = "孙悟空" ; age = 18; gender = "男"
可以用 XML 表示为
<student>
<name>孙悟空name>
<age>18age>
<gender>男gender>
student>
现在,服务器返回的都是 JSON 格式的数据,XML 格式已经被 JSON 取代了。JSON 表示为
{
"name":"孙悟空", "age":18, "gender":"男"}
a.com
网页打算向 b.com
网页发送请求,Ajax 默认是不允许的。
AJAX 的核心是 XMLHttpRequest 对象。它用于同幕后服务器交换数据,这意味着可以更新网页的部分,而不需要重新加载整个页面。
const xhr = new XMLHttpRequest();
如需向服务器发送请求,我们使用 XMLHttpRequest 对象的 open()
和 send()
方法。如下:
xhr.open('GET', 'http://127.0.0.1:8000/server');
// 3. 发送
xhr.send();
xhr.open('POST', 'http://127.0.0.1:8000/server');
xhr.send();
如需像 HTML 表单那样 POST 数据,需要通过 setRequestHeader()
添加一个 HTTP 头部。
xhr.open('POST', 'http://127.0.0.1:8000/server');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('a=100&b=200&c=300');
初始化 HTTP 请求参数,但不会发送请求。
xhr.open(method, url [, async][,user][,pwd])
method
:要使用的 HTTP 方法,比如 GET
、POST
等。url
:要向其发送请求的 URL 。async
:可选,表示是否异步执行操作,默认为 true
。true
表示通过异步发送请求;false
表示同步发送请求,将停止执行直到服务器响应就绪(不推荐使用)。user
:可选,用户名称。pwd
:可选,密码。这个方法导致一个 HTTP 请求发送。
xhr.send(body)
GET 请求不传 body 参数,只有 POST 请求使用。
如果之前没有调用 open()
,或者更具体地说,如果 readyState 不是 1,send()
抛出一个异常。否则,它发送一个 HTTP 请求,该请求由以下几部分组成:
open()
时指定的 HTTP 方法、URL 以及认证资格(如果有的话)。setRequestHeader()
时指定的请求头部(如果有的话)。向请求添加 HTTP 头部,也就是设置请求头信息。此方法必须在 open()
方法和 send()
之间调用。
setRequestHeader(header, value)
一般我们设置的是:content-type,传输数据类型,即服务器需要我们传送的数据类型
xhr.setRequestHeader ("content-type", "application/x-www-form-urlencoded" )
readyState 保存了 XMLHttpRequest 的状态。其属性值对应描述如下:
属性值 | 描述 |
---|---|
0 |
XMLHttpRequest 对象已创建或已被 abort() 方法重置 |
1 |
open() 方法已调用, send() 方法未调用。请求还没有被发送 |
2 |
send() 方法已调用,HTTP 请求已发送到 Web 服务器,但还未接收到响应 |
3 |
所有响应头部都已经接收到,响应体开始接收但未完成 |
4 |
请求已完成且 HTTP 响应已经完全接收 |
每当 readyState 发生变化时就会调用 onreadystatechange
函数。
请求的状态码,HTTP 响应中状态行的一部分。不同的状态码代表不同的含义,如下:
状态码 | 描述 |
---|---|
1xx | 表示 HTTP 请求已经接受,继续处理请求 |
2xx | 表示 HTTP 请求已经处理完成 |
3xx | 表示把请求访问的 URL 重定向到其他目录 |
4xx | 表示客户端出现错误 |
5xx | 表示服务器端出现错误 |
常用的状态码:
状态码 | 描述 |
---|---|
200 | 表明该请求被成功地完成,所请求的资源发送回客户端 |
403 | Forbidden 禁止访问 |
404 | Not Found 资源不存在 |
onreadystatechange 属性定义当 readyState 发生变化时执行的函数。
看下面示例。
xhr.onreadystatechange = () => {
// 判断
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果
document.querySelector('div').innerHTML = xhr.response;
}
}
}
如上代码表示:当可以成功访问且有响应时,将响应信息写入到 div 中。
XMLHttpRequest 属性 responseType 是一个枚举字符串值,用于指定响应中包含的数据类型。它还允许作者更改响应类型。如果将 responseType 的值设置为空字符串,则会使用 text
作为默认值。
值 | 描述 |
---|---|
"" |
与默认类型 “text” 相同 |
"arraybuffer" |
response 是一个包含二进制数据的 JavaScript ArrayBuffer |
"blob" |
response 是一个包含二进制数据的 Blob 对象 |
"document" |
response 是一个 HTML Document 或 XML XMLDocument,根据接收到的数据的 MIME 类型而定。 |
"text" |
response 是 DOMString 对象中的文本 |
"json" |
response 是通过将接收到的数据内容解析为 JSON 而创建的 JavaScript 对象 |
如下示例,设置响应体数据类型为 json
xhr.responseType = 'json';
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// {name: "zhangsan"}
result.innerHTML = xhr.response.name; // zhangsan
}
}
}
当然,你也可以手动对数据进行转换,只不过显得有些麻烦。如下
// {name: "zhangsan"}
let data = JSON.parse(xhr.response);
result.innerHTML = data.name; // zhangsan
下面两个示例,分别为向服务器发送 GET 和 POST 请求。
需求:点击按钮,向服务端发送 GET 请求;响应结果在 div 呈现
前端页面 index.html
<button>点击发送请求button>
<div id="result">div>
<script>
// 绑定事件
const btn = document.querySelector('button');
const result = document.querySelector('#result');
btn.addEventListener('click', () => {
// 1. 创建对象
const xhr = new XMLHttpRequest();
// 2. 初始化:设置请求方法 和 url
xhr.open('GET', 'http://127.0.0.1:8000/server');
// 3. 发送
xhr.send();
// 4. 事件绑定:处理服务端返回结果
xhr.onreadystatechange = () => {
// readystate 是 xhr 对象的属性: 表示状态 0 1 2 3 4
if (xhr.readyState === 4) {
// 判断响应状态码 200 401 403 404 500
// 2xx 表示 成功
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果:行 头 空行 体
result.innerHTML = xhr.response;
} else {
}
}
}
})
script>
服务器端 sever.js
const express = require('express');
// 创建应用对象
const app = express();
// 创建路由规则
app.get('/sever', (req, res) => {
// 设置响应头:设置允许跨域
res.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应
res.send('Hello AJAX');
})
// 监听端口启动服务
app.listen(8000, () => {
console.log('服务已经启动, 8000 端口监听中...');
})
前端页面 index.html
<div id="result">div>
<script>
const result = document.querySelector('#result');
result.addEventListener('mouseenter', function () {
// 1. 创建对象
const xhr = new XMLHttpRequest();
// 2. 初始化
xhr.open('POST', 'http://127.0.0.1:8000/server');
// 3. 发送
xhr.send();
xhr.onreadystatechange = () => {
// 判断
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 处理结果
result.innerHTML = xhr.response;
}
}
}
})
script>
服务器端 sever.js
const express = require('express');
// 创建应用对象
const app = express();
// 创建路由规则
app.post('/sever', (req, res) => {
// 设置响应头:设置允许跨域
res.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应
res.send('Hello AJAX POST');
})
// 监听端口启动服务
app.listen(8000, () => {
console.log('服务已经启动, 8000 端口监听中...');
})
我们可以使用一个超时设置来设置一个时间,到时自动取消请求。进而避免代码为了等候读取请求的返回数据长时间执行。
超时毫秒数可以通过为 XMLHttpRequest 对象的 timeout
属性赋值来指定:
xhr.timeout = 2000; // 指定超时时间 2s
同时还可以为 timeout 事件的 ontimeout
事件句柄指定事件处理函数,如下:
xhr.ontimeout = () => {
alert('请求超时,稍后重试'); // 超时后触发
}
XMLHttpRequestEventTarget.onerror 是 XMLHttpRequest 事务由于错误而失败时调用的函数。
请注意只有在网络层级出现错误时才会调用此函数。如果错误只出现在应用层(比如发送一个HTTP的错误码),这个方法将不会被调用。
// 网络异常
xhr.onerror = () => {
alert('你的网络似乎除了一些问题'); // 网络异常时触发
}
XMLHttpRequest.abort()
方法:如果该请求已被发出,利用此方法将终止该请求。
const btns = document.querySelectorAll('button');
let xhr = null;
btns[0].addEventListener('click', () => {
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8000/delay');
xhr.send();
// 不需要返回什么结果,可以不加事件绑定
})
// abort
btns[1].addEventListener('click', () => {
xhr.abort();
})
如果同意请求被重复发送,会使得服务器压力比较大,效率变低的问题。
解决方法:创建标识变量,通过标识变量判断此前的请求是否已经完成,未完成则利用 abort()
取消此次请求。
const btn = document.querySelector('button');
let xhr = null;
// 标识变量:是否正在发送 AJAX 请求
let isSending = false;
btn.addEventListener('click', () => {
// 首先判断标识变量
if (isSending) x.abort();
xhr = new XMLHttpRequest();
isSending = true;
xhr.open('GET', 'http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
isSending = false;
}
}
})
详细内容可查阅文档 :jQuery API - AJAX
通过 HTTP 请求加载远程数据。这是 jQuery 底层 AJAX 实现。简单易用的高层实现见 $.get
,$.post
等。
$.ajax()
返回其创建的 XMLHttpRequest 对象。
$.ajax(url,[settings])
url
:一个用来包含发送请求的 URL 字符串。settings
:AJAX 请求设置。所有选项都是可选的。可选的选项有很多,这里简单列举一些常用的作为说明。
data
:发送到服务器的数据。将自动转换为请求字符串格式。dataType
:指定服务器返回的数据类型。如,xml
、html
、json
、script
、text
type
:请求方式。默认 GET 请求,也可以设置为 POST。注意:其他 HTTP 请求方法,如 PUT 和 DELETE 也可以使用,但仅部分浏览器支持。timeout
:设置请求超时时间。headers
:设置头信息。async
:(默认: true) 默认设置下,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为 false。除此外,还有几种回调函数可作为参数选项
beforeSend(XHR)
:发送请求前可修改 XMLHttpRequest 对象的函数,如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。success(data, textStatus, jqXHR)
:请求成功后的回调函数。参数:由服务器返回,并根据 dataType
参数进行处理后的数据;描述状态的字符串。还有 jqXHR(在jQuery 1.4.x的中,XMLHttpRequest) 对象 。在jQuery 1.5, 成功设置可以接受一个函数数组。每个函数将被依次调用。error
:请求失败时调用此函数。有以下三个参数:XMLHttpRequest 对象、错误信息、(可选)捕获的异常对象。如果发生了错误,错误信息(第二个参数)除了得到null之外,还可能是 "timeout"
,"error"
,"notmodified"
和 "parsererror"
。complete(XHR, TS)
:请求完成后回调函数 (请求成功或失败之后均调用)。参数: XMLHttpRequest 对象和一个描述成功请求类型的字符串。 $('button').eq(2).click(() => {
$.ajax({
// url
url: 'http://127.0.0.1:8000/jquery-server',
// 参数
data: {
a: 100, b: 200 },
// 请求类型
type: 'GET',
// 响应体结果
dataType: 'json',
// 成功的回调
success: (data) => {
console.log(data);
},
// 超时时间
timeout: 2000,
// 失败的回调
error: () => {
console.log('出错啦.....');
},
// 头信息
headers: {
c: 300,
d: 400
}
});
})
通过远程 HTTP GET 请求载入信息。请求成功时可调用回调函数。如果需要在出错时执行函数,请使用 $.ajax
。
$.get(url, [data], [callback], [type])
url
:请求的 URL 地址。data
:请求携带的参数。callback
:载入成功时回调函数。可以接收响应体参数(data
)。type
:设置响应体类型。如,xml
, html
, script
, json
, text
, _default
。请求 test.php 网页,忽略返回值。
$.get("test.php");
请求 test.php 网页,传送 2 个参数,忽略返回值。
$.get("test.php", {
name: "John", time: "2pm" } );
请求 http://127.0.0.1:8000/jquery-server 网页,传送 2 个参数,添加回调,成功时打印以 json 格式打印回调信息。
$('button').eq(0).click(() => {
$.get('http://127.0.0.1:8000/jquery-server', {
a: 100,
b: 200
}, (data) => {
console.log(data);
}, 'json');
})
和 GET 请求相似。通过远程 HTTP POST 请求载入信息。
$.post(url, [data], [callback], [type])
url
:请求的 URL 地址。data
:请求携带的参数。callback
:载入成功时回调函数。type
:设置返回内容格式,xml
, html
, script
, json
, text
, _default
。 $('button').eq(1).click(() => {
$.post('http://127.0.0.1:8000/jquery-server', {
a: 100,
b: 200
}, (data) => {
console.log(data);
});
})
官方文档:axios 中文文档
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。简单的讲就是可以发送 GET、POST 请求。
$ npm install axios
$ bower install axios
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
// 配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000';
btns[0].onclick = function () {
axios.get('/axios-server', {
// url 参数
params: {
id: 100,
vip: 7
},
// 请求头信息
headers: {
name: 'zs',
age: 18
}
}).then(value => {
console.log(value);
});
}
axios.post(url[, data[, config]])
示例
axios.post('/axios-server', {
// 请求体
username: 'admin',
password: 'admin'
}, {
// url
params: {
id: 200,
vip: 9
},
// 请求头参数
headers: {
height: 180,
weight: 170
}
})
可以通过向 axios 传递相关配置来创建请求。
axios(config)
示例如下
axios({
// 请求方法
method: 'POST',
// url
url: '/axios-server',
// url 参数
params: {
vip: 10,
level: 30
},
// 头信息
headers: {
a: 100,
b: 200
},
// 请求体参数
data: {
username: 'admin',
password: 'admin'
}
}).then(response => {
// 响应状态码
console.log(response.status);
// 响应状态字符串
console.log(response.statusText);
// 响应头信息
console.log(response.headers);
// 响应体
console.log(response.data);
})
fetch()
方法用于发起获取资源的请求。它返回一个 Promise,这个 Promise 会在请求响应后被 resolve,并传回 Response 对象。
fetch()
方法的参数与 Request()
构造器是一样的。
fetch('http://127.0.0.1:8000/fetch-server', {
// 请求方法
method: 'POST',
// 请求头
headers: {
name: 'zs'
},
// 请求体
body: 'username=admin&password=admin'
}).then(response => {
return response.text();
}).then(response => {
console.log(response);
});
参考:
1) W3school - AJAX 教程
2)【尚硅谷】3小时 Ajax 入门到精通