1 AJAX简介
Ajax = Asynchronous Javascript And XML,即异步JavaScript和XML,它最大的特点就是能够在网页不刷新的情况下向服务端发送HTTP请求,然后得到HTTP响应。AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
1.1 AJAX的优点
- 可以无需刷新页面与服务器进行交互
- 运行根据用户事件来更新部分页面内容
1.2 AJAX的缺点
- 没有浏览历史,不能回退
- 存在跨域问题
- SEO问题
2 XML简介
之所以在AJAX中提到XML是因为最初AJAX在进行数据交换的时候就是使用XML格式的数据(服务端给客户端返回的数据就是XML格式的,客户端再解析XML得到数据),XML 指可扩展标记语言(eXtensible Markup Language),XML 被设计用来传输和存储数据,如:
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
可以看到XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全部都是自定义标签。
不过现在进行AJAX操作时,不再使用XML了,都是使用JSON格式了,这种数据格式更加灵活方便。
3 JSON简介
JSON = JavaScript Object Notation,即JavaScript 对象表示法,JSON 是存储和交换文本信息的语法,类似 XML。JSON 比 XML 更小、更快,更易解析,如:
{
"sites": [
{ "name":"百度" , "url":"www.baidu.com" },
{ "name":"谷歌" , "url":"www.google.com" },
]
}
4 HTTP协议请求报文与响应报文的格式
HTTP = HyperText Transfer Protocol,即超文本传输协议,协议详细规定了浏览器和万维网服务器之间互相通信的规则。
4.1 请求报文
一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成,下图给出了请求报文的一般格式:
4.2 响应报文
HTTP响应报文由状态行、响应头部、空行 和 响应包体 4 个部分组成,如下图所示:
5 AJAX请求的基本操作
新建文件夹,输入命令:npm init --yes
,初始化项目,输入npm i express
安装Express框架,新建express.js
,添加如下代码:
const express = require('express')
const app = express()
app.get('/msg', (request, response) => {
// 设置响应头,允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应体
response.send('ok')
})
app.listen(3000, () => {
console.log('服务已启动,监听3000端口')
})
输入node express.js
命令后即可启动服务(建议使用nodemon工具,输入命令nodemon express.js
后可以实现热更新)。在页面中发送请求的代码如下:
function send() {
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://127.0.0.1:3000/msg')
xhr.send()
xhr.onreadystatechange = function() {
// 服务端返回了所有结果
if (xhr.readyState === 4) {
// 响应成功,状态码首位为2时,代表请求成功
if (xhr.status >= 200 && xhr.status < 300) {
// 1.响应行
console.log(xhr.status)
// 2.响应状态字符串
console.log(xhr.statusText)
// 3.所有响应头
console.log(xhr.getAllResponseHeaders())
// 4.响应体
console.log(xhr.response)
}
}
}
}
控制台输出结果如下:
200
OK
content-length: 2
content-type: text/html; charset=utf-8
ok
6 AJAX设置请求参数
请求参数的添加方法可以在请求URL后面跟上“?
”,再接上等式,如“?a=1
”,若需要添加多个参数,则使用“&
”分隔即可:
xhr.open('GET', 'http://127.0.0.1:3000/msg?a=1&b=2')
发送请求后,可以在Chrome浏览器的开发者调试工具“Network”中选择该请求,在右侧的“Headers”中看到“Query String Parameters”:
7 AJAX发送POST请求
在express.js
中添加处理POST请求的路由:
const express = require('express')
const app = express()
app.get('/msg', (request, response) => {
// 设置响应头,运行跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应体
response.send('ok')
})
+ app.post('/msg', (request, response) => {
+ response.setHeader('Access-Control-Allow-Origin', '*')
+ response.send('POST OK')
+ })
app.listen(3000, () => {
console.log('服务已启动,监听3000端口')
})
页面中发送请求的代码如下:
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://127.0.0.1:3000/msg')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// 响应成功,状态码首位为2时,代表请求成功
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
发送请求后输出:“POST OK”。另外,在发送POST请求时可以手动设置请求体,可以把请求体放在xhr.send()
的参数中:
function send() {
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://127.0.0.1:3000/msg')
+ xhr.send('a=1&b=2')
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// 响应成功,状态码首位为2时,代表请求成功
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
发送POST请求后,可以在开发者调试工具中看到:
8 AJAX中设置请求头信息
设置请求头的方法为setRequestHeader
,它必须在open
后send
前,如:
function send() {
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://127.0.0.1:3000/msg')
// 设置请求头信息
+ xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send('a=1&b=2')
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
此外还可以自定义请求头,如:xhr.setRequestHeader('MyRequestHeader', 'test')
,不过设置这种请求头后发送请求会触发安全机制。
9 服务端响应JSON数据
在express.js
中添加如下代码:
app.get('/json', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
const jsonData = {
name: 'syz'
}
// 对对象进行字符串转换
let str = JSON.stringify(jsonData)
// send只能发送字符串
response.send(str)
})
发送请求的代码如下:
function send() {
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://127.0.0.1:3000/json')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
输出结果:{"name":"syz"}
,注意这里只是字符串的形式,客户端要对该数据进行处理,则需要将字符串转换为对象:
function send() {
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://127.0.0.1:3000/json')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
+ // 字符串转换为对象
+ let data = JSON.parse(xhr.response)
+ console.log(data)
}
}
}
}
这样输出的结果就为对象的形式。此外还有一种自动转换的方式,这种方式需要借助于XMLHttpRequest
对象上的respnseType
属性:
function send() {
const xhr = new XMLHttpRequest()
+ // 将响应类型设置为json
+ xhr.responseType = 'json'
xhr.open('GET', 'http://127.0.0.1:3000/json')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
这样输出的结果也是对象的形式,这种方式更加的方便。
10 AJAX请求超时与异常处理
修改express.js
中的msg
接口,将其设置为4秒后再返回结果:
app.post('/msg', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(() => {
response.send('POST OK')
}, 4000);
})
页面中的访问方法如下:
function send() {
const xhr = new XMLHttpRequest()
// 超时设置,设置为2秒,若2秒后还没有得到结果,则请求取消
xhr.timeout = 2000
xhr.open('POST', 'http://127.0.0.1:3000/msg')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
发送请求后可以看到请求的状态在2秒后变为了canceled
:
还可以为超时设置回调函数,如:
function send() {
const xhr = new XMLHttpRequest()
// 超时设置,设置为2秒,若2秒后还没有得到结果,则请求取消
xhr.timeout = 2000
+ // 超时回调
+ xhr.ontimeout = function() {
+ console.log('请求超时,请稍后再试!')
+ }
xhr.open('POST', 'http://127.0.0.1:3000/msg')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
还可以设置网络异常的回调,如没有网络:
function send() {
const xhr = new XMLHttpRequest()
// 超时设置,设置为2秒,若2秒后还没有得到结果,则请求取消
xhr.timeout = 2000
// 超时回调
xhr.ontimeout = function() {
console.log('请求超时,请稍后再试!')
}
+ // 异常回调
+ xhr.onerror = function() {
+ console.log('网络异常,请检查网络连接是否正确!')
+ }
xhr.open('POST', 'http://127.0.0.1:3000/msg')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
11 AJAX取消请求
取消请求需要使用XMLHttpRequest
上的abort
方法:
+ let xhr = null
function send() {
xhr = new XMLHttpRequest()
xhr.open('POST', 'http://127.0.0.1:3000/msg')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
+ function cancelSend() {
+ xhr.abort()
+ }
12 AJAX处理重复请求
let xhr = null
// 标识变量,当前是否在发送AJAX请求
let isSending = false
function send() {
// 如果已经发送了,则取消上一次的请求,创建一个新的请求
if (isSending) {
xhr.abort()
}
// 在发送请求
isSending = true
xhr = new XMLHttpRequest()
xhr.open('POST', 'http://127.0.0.1:3000/msg')
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// 发送请求成功
isSending = false
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response)
}
}
}
}
13 JQuery中发送AJAX请求
13.1 发送GET请求
第一个参数为请求的URL,第二个参数为请求参数,第二个参数为请求的回调。
$.get('http://127.0.0.1:3000/msg', {a:1, b:2}, function(data) {
console.log(data)
})
还可以传入第四个参数,第四个参数则是响应体类型,如:
$.get('http://127.0.0.1:3000/msg', {a:1, b:2}, function(data) {
console.log(data)
}, 'json')
这里就将响应体的类型设置为了JSON格式。
13.2 发送POST请求
发送POST请求的方法与发送GET请求的方法类似:
$.post('http://127.0.0.1:3000/msg', {a:1, b:2}, function(data) {
console.log(data)
})
13.3 发送请求通用方法
JQuery中发送请求的通用方法为$
对象上的ajax
方法,该方法接收的参数为一个对象:
$.ajax({
// url
url: 'http://127.0.0.1:3000/msg',
// 参数
data: {a:1, b:2},
// 请求类型
type: 'GET',
// 响应体结果的类型
dataType: 'json',
// 成功的回调
success: function(data) {
console.log(data)
},
// 失败的回调
error: function() {
console.log('err')
},
// 超时时间
timeout: 4000,
// 头信息
headers: {
// MyHeaders: 123
}
})
14 Axios中发送AJAX请求
Axios是目前前端领域中最热门的AJAX工具库,也是Vue和React官方推荐的工具库。
14.1 Axios发送GET请求
axios.defaults.baseURL = 'http://127.0.0.1:3000'
axios.get('/msg', {
// url参数
params: {
a: 1,
b: 2
},
// 设置请求头信息
headers: {
MyHeaders: 123
}
}).then(value => {
// 基于Promise
console.log(value)
})
14.2 Axios发送POST请求
发送POST请求可以设置请求体信息,放在post
方法的第二个参数:
axios.defaults.baseURL = 'http://127.0.0.1:3000'
axios.post('/msg', {
username: 'admin',
password: '123456'
}, {
// url参数
params: {
a: 1,
b: 2
},
// 设置请求头信息
headers: {
MyHeaders: 123
},
}).then(value => {
// 基于Promise
console.log(value)
})
14.3 Axios发送请求通用方法
axios.defaults.baseURL = 'http://127.0.0.1:3000'
axios({
// 请求方法
method: 'POST',
// url
url: '/msg',
// url参数
params: {
a: 1,
b: 2
},
// 头信息
headers: {
MyHeaders: 123
},
// 请求体参数
data: {
username: 'admin',
password: '123456'
}
})
15 fetch方法发送AJAX请求
fetch
方法全局自带,并且返回一个Promise对象。
fetch('http://127.0.0.1:3000/msg', {
// 请求方法
method: 'POST',
// 请求头
headers: {
MyHeaders: 123
},
// 请求体
body: 'username=admin&password=123456'
}).then((response) => {
// 调用fetch中的text方法,再返回一个Promise对象
return response.text()
// 如果服务器返回的是json数据,可以使用json方法
// return response.json()
}).then((response) => {
// 获取到最终的响应数据
console.log(response)
})