AJAX 全称为Asynchronous Javascript And XML,就是异步的 JS 和 XML。 最大的优势:无刷新发送请求和获取数据。存在于浏览器中Ajax引擎。
xhr:jq/axios对xhr封装
fetch:挂载到window上,兼容性差。
1 xhr
function axios({url, params={}, data={}, method='GET'}) {
// 返回一个promise对象
return new Promise((resolve, reject) => {
// 创建一个XHR对象
const request = new XMLHttpRequest()
// 根据params拼接query参数:id=1&name=xxx转为json
let queryStr = Object.keys(params).reduce((pre, key) => {
pre += `&${key}=${params[key]}`
return pre
}, '')
if (queryStr.length>0) {
queryStr = queryStr.substring(1)
url += '?' + queryStr
}
// 请求方式转换为大写
method = method.toUpperCase()
// 初始化一个异步请求(还没发请求)
request.open(method, url, true)
// 绑定请求状态改变的监听
request.onreadystatechange = function () {
// 如果状态值不为4, 直接结束(请求还没有结束)
if (request.readyState !== 4) {
return
}
// 如果响应码在200~~299之间, 说明请求都是成功的
if (request.status>=200 && request.status<300) {
// 准备响应数据对象
const responseData = {
data: request.response,
status: request.status,
statusText: request.statusText
}
// 指定promise成功及结果值
resolve(responseData)
} else { // 请求失败了
// 指定promise失败及结果值
const error = new Error('request error staus '+ request.status)
reject(error)
}
}
// 指定响应数据格式为json ==> 内部就是自动解析好
request.responseType = 'json'
// 如果是post/put请求
if (method==='POST' || method==='PUT') {
// 设置请求头: 使请求体参数以json形式传递
request.setRequestHeader('Content-Type', 'application/json;charset=utf-8')
// 包含所有请求参数的对象转换为json格式
const dataJson = JSON.stringify(data)
// 发送请求, 指定请求体数据
request.send(dataJson)
} else {// GET/DELETE请求
// 发送请求
request.send(null)
}
})
}
2 jquery
$(function () {
// 1. 测试GET接口
$('#btnGET').on('click', function () {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1/api/get',
data: { name: 'zs', age: 20 },
success: function (res) {
console.log(res)
},
})
})
// 2. 测试POST接口
$('#btnPOST').on('click', function () {
$.ajax({
type: 'POST',
url: 'http://127.0.0.1/api/post',
data: { bookname: '水浒传', author: '施耐庵' },
success: function (res) {
console.log(res)
},
})
})
// 3. 为删除按钮绑定点击事件处理函数
$('#btnDelete').on('click', function () {
$.ajax({
type: 'DELETE',
url: 'http://127.0.0.1/api/delete',
success: function (res) {
console.log(res)
},
})
})
// 4. 为 JSONP 按钮绑定点击事件处理函数
$('#btnJSONP').on('click', function () {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1/api/jsonp',
dataType: 'jsonp',
success: function (res) {
console.log(res)
},
})
})
})
3 axios
3.1 发送请求
baseURL配置公共路径,create()根据指定配置创建一个新的axios,应用到不同要求的接口请求中。
import axios from 'axios'
axios.get(`/api1/search/users2?q=${keyWord}`).then(
response => {成功回调},
error => {失败回调}
)
//async await简化
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}
//get参数
axios.get('/user', {
params: {
ID: 12345
}
})
//post参数
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
// 指定默认配置
axios.defaults.baseURL = 'http://localhost:3000'
// 根据指定配置创建一个新的axios,新axios只是没有取消请求和批量发请求的方法
const instance = axios.create({
baseURL: 'http://localhost:4000'
})
// 使用instance发请求
instance.get('/xxx')
/* 1. GET请求: 从服务器端获取数据*/
function testGet() {
// axios.get('/posts?id=1')
axios({
url: '/posts',
params: {
id: 1
}
})
.then(response => {
console.log('/posts get', response.data)
})
}
/* 2. POST请求: 向服务器端添加新数据*/
function testPost() {
// axios.post('/posts', {"title": "json-server3", "author": "typicode3"})
axios({
url: '/posts',
method: 'post',
data: {"title": "json-server4", "author": "typicode4"}
})
.then(response => {
console.log('/posts post', response.data)
})
}
/* 3. PUT请求: 更新服务器端已经数据 */
function testPut() {
// axios.put('http://localhost:3000/posts/4', {"title": "json-server...", "author": "typicode..."})
axios({
url: '/posts/4',
method: 'put',
data: {"title": "json-server5", "author": "typicode5"}
})
.then(response => {
console.log('/posts put', response.data)
})
}
/* 4. DELETE请求: 删除服务器端数据 */
function testDelete() {
// axios.delete('http://localhost:3000/posts/4')
axios({
url: '/posts/5',
method: 'delete'
})
.then(response => {
console.log('/posts delete', response.data)
})
}
3.2 拦截器
axios.interceptors.request.use(
config => {
config.headers.Authorization = token;
showFullScreenLoading();
return config;//是为了串联操作,向后传递
},
error => {
return Promise.reject(error);//是为了串联操作,向后传递
}
);
axios.interceptors.response.use(
response=> {
tryHideFullScreenLoading();
return response;
}
error => {
return Promise.reject(error);
}
);
3.3 取消请求
执行cancel函数,传入错误信息message
内部会让cancelPromise变为成功,且成功的值为一个Cancel对象
在cancelPromise的成功回调中中断请求,并让发请求的promise失败,失败的reason为Cancel对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>取消请求</title>
</head>
<body>
<button onclick="getProducts1()">获取商品列表1</button><br>
<button onclick="getProducts2()">获取商品列表2</button><br>
<button onclick="cancelReq()">取消请求</button><br>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
<script>
// 添加请求拦截器
axios.interceptors.request.use((config) => {
// 在准备发请求前, 取消未完成的请求
if (typeof cancel==='function') {
cancel('取消请求')
}
// 添加一个cancelToken的配置
config.cancelToken = new axios.CancelToken((c) => { // c是用于取消当前请求的函数
// 保存取消函数, 用于之后可能需要取消当前请求
cancel = c
})
return config
})
// 添加响应拦截器
axios.interceptors.response.use(
response => {
cancel = null
return response
},
error => {
if (axios.isCancel(error)) {// 取消请求的错误
// cancel = null
console.log('请求取消的错误', error.message) // 做相应处理
// 中断promise链接
return new Promise(() => {})
} else { // 请求出错了
cancel = null
// 将错误向下传递
// throw error
return Promise.reject(error)
}
}
)
let cancel // 用于保存取消请求的函数
function getProducts1() {
axios({
url: 'http://localhost:4000/products1',
}).then(
response => {
console.log('请求1成功了', response.data)
},
error => {// 只用处理请求失败的情况, 取消请求的错误的不用
console.log('请求1失败了', error.message)
}
)
}
function getProducts2() {
axios({
url: 'http://localhost:4000/products2',
}).then(
response => {
console.log('请求2成功了', response.data)
},
error => {
console.log('请求2失败了', error.message)
}
)
}
function cancelReq() {
// 执行取消请求的函数
if (typeof cancel === 'function') {
cancel('强制取消请求')
} else {
console.log('没有可取消的请求')//pending状态才需要取消,取消后会进入失败的回调
}
}
</script>
</body>
</html>
4 fetch
fetch(`/api1/search/users2?q=${keyWord}`).then(
response => {
console.log('联系服务器成功了');
return response.json()//返回promise实例
},
).then(
response => {console.log('获取数据成功了',response);},
).catch(
error => {
console.log('请求出错',error);
}
)
//优化版
try {
const response= await fetch(`/api1/search/users2?q=${keyWord}`)
const data = await response.json()
console.log(data);
} catch (error) {
console.log('请求出错',error);
}