一.XMLHttpRequest
1.1 Ajax和XMLHttpRequest
当我们在浏览器输入一个url时,发生的是什么?是的,我们请求这个地址的全部资源。
但是我们经常可以看到,比如逛某宝时,一页看完了后下拉,会又刷新几列商品出来,然而上面的内容是没有变的。可以想象,如果每次都要重新请求整个页面,那样对服务器的压力是非常大的。
这时就要用到Ajax编程。Ajax的核心是XMLHttpRequest,使用XMLHttpRequest(XHR)对象可以与服务器交互。你可以从URL获取数据,而无需让整个的页面刷新。这允许网页在不影响用户的操作的情况下更新页面的局部内容。
1.2 理解
- ajax 请求是一种特别的 http 请求
- 对服务器端来说, 没有任何区别, 区别在浏览器端
- 浏览器端发请求: 只有 XHR 或 fetch 发出的才是 ajax 请求, 其它所有的都是
非 ajax 请求 - 浏览器端接收到响应
(1) 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/
跳转页面
(2) ajax 请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调
函数并传入响应相关数据
1.3 怎么用
虽然名字叫XML,但XMLHttpRequest 可以用于获取任何类型的数据,而不仅仅是XML,它甚至支持 HTTP 以外的协议(包括 file:// 和 FTP)。
让我们看看MDN文档。
二.自定义ajax封装(简易版axios)
2.1 特点
- 函数的返回值为 promise, 成功的结果为 response, 异常的结果为 error
- 能处理多种类型的请求: GET/POST/PUT/DELETE
- 函数的参数为一个配置对象
{
url: ‘’, // 请求地址
method: ‘’, // 请求方式 GET/POST/PUT/DELETE
params: {}, // GET/DELETE 请求的 query 参数
data: {}, // POST 或 DELETE 请求的请求体参数
} - 响应 json 数据自动解析为 js
2.2 代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button onclick="testGET()">send GET</button>
<button onclick="testPOST()">send POST</button>
<button onclick="testPUT()">send PUT</button>
<button onclick="testDELETE()">send DELETE</button>
</body>
<script>
function axios({
url,
method='GET',
params={},
data={}
}){
//add query string to url
let queryString = '?'
Object.keys(params).forEach(key => {
queryString += (key + '=' + params[key] + '&')
})
if(queryString.length > 1) {
queryString = queryString.substr(0, queryString.length - 1)
url += queryString
}
//return new Promise
return new Promise((resolve,reject) => {
const xrh = new XMLHttpRequest()
xrh.open(method, url)
//judge the request method
if(method==='GET' || method==='DELETE'){
xrh.send()
}else if(method==='POST' || method==='PUT'){
xrh.setRequestHeader('Content-Type','application/json;charset=utf-8')
xrh.send(JSON.stringify(data))
}
//listen the status change
xrh.onreadystatechange = function() {
//请求未完成,直接返回
if(xrh.readyState !== 4){
return
}
const {status, statusText} = xrh
const response = {
data: JSON.parse(xrh.response),
status,
statusText
}
//请求成功,调用reslove,失败reject
if (status>=200 && status<300) {
resolve(response)
} else {
reject(new Error('response status is '+status))
}
}
})
}
function testGET() {
axios({
url: 'http://localhost:3000/posts',
method: 'GET',
params: {
id:007,
name:'zhangsan'
}
}).then(
value => {
console.log(value);
}
)
}
function testPOST() {
axios({
url: 'http://localhost:3000/posts',
method: 'POST',
data: {
'title':'server2',
'author':'nobody'
}
}).then(
response => {
console.log(response);
},
error => {
alert(error.message)
}
)
}
function testDELETE() {
axios({
url: 'http://localhost:3000/posts/7',
method: 'DELETE',
}).then(
res => {
console.log(res);
},
err => {
console.log(err);
}
)
}
function testPUT() {
axios({
url: 'http://localhost:3000/posts/5',
method: 'PUT',
data: {
title: 'server5',
author: 'LILEI'
}
})
}
</script>
</html>